函数

1.声明语法:func 函数名 (参数列表) [(返回值列表)] {}

2.golang函数特点:

a. 不支持重载,一个包不能有两个名字一样的函数

b. 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量

c. 匿名函数

d. 多返回值

定义函数类型type:

package main

import "fmt"

type add_func func(int, int) int

func add(a, b int) int {
return a + b
} func sub(a, b int) int {
return a - b
} func operator(op add_func, a int, b int) int {
return op(a, b)
} func main() {
c := add
fmt.Println(c)
sum := operator(c, 100, 200)
fmt.Println(sum) var x add_func
x=sub
fmt.Println(x)
sub := operator(x, 100, 200)
fmt.Println(sub) }

3.函数参数传递方式:

1). 值传递

2). 引用传递

注意1:无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。

引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。

注意2:map、slice、chan、指针、interface默认以引用的方式传递

package main

import "fmt"

func modify(a *int) {
*a = 100
} func main() {
a := 8
fmt.Println(a)
modify(&a)
fmt.Println(a)
}

参数类型省略:

func f(i, j, k int, s, t string)
func f(i int, j int, k int, s string, t string)

4.命名返回值的名字:

package main
import "fmt"
func split(sum int) (x, y int) {
x = sum / 10
y = sum % 10
return
}
func main() {
fmt.Println(split(17))
}

_标识符,用来忽略返回值

5.可变参数:

func add(arg …int) int {
}//0个或多个参数
func add(a int, arg …int) int {
}//1个或多个参数
func add(a int, b int, arg …int) int {
}//2个或多个参数

注意:其中arg是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数

练习:写一个函数add,支持1个或多个int相加,并返回相加结果

练习:写一个函数concat,支持1个或多个string相拼接,并返回结果

defer

1.当函数返回时,执行defer语句。可以用来做资源清理

2.多个defer语句,按先进后出的方式执行,即最后一个defer语句将最先被执行

3.defer语句中的变量,在defer声明时就决定了。

在函数将要返回前执行:

package main

import "fmt"

func print() {
defer func() {
fmt.Println("defer")
}()
fmt.Println("hello")
} func main() {
print()
}

多个defer语句:

package main

import "fmt"

func main()  {
var i int =1
fmt.Println(i)
defer fmt.Println(i)
//不会立即执行,压到栈里面,函数执行结束后,再执行栈里的
defer fmt.Println("a")
i=10
fmt.Println(i)
}

用途:

1.关闭文件句柄

2.锁资源释放

3.数据库连接释放

内置函数

1.close:主要用来关闭channel

2.len:用来求长度,比如string、array、slice、map、channel

3.new:用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针

package main

import "fmt"

func main()  {
var i int
fmt.Println(i) j := new(int)
fmt.Println(j)
fmt.Println(*j) *j = 100
fmt.Println(*j)
}

4.make:用来分配内存,主要用来分配引用类型,比如chan、map、slice

new和make的区别:

package main

import "fmt"

func test() {
s1 := new([]int)
fmt.Println(s1) s2 := make([]int, 10)
fmt.Println(s2) *s1 = make([]int, 5)
(*s1)[0] = 100
s2[0] = 100
fmt.Println(s1)
fmt.Println(s2)
return
} func main() {
test()
}

5.append:用来追加元素到数组、slice中

package main

import "fmt"

func main()  {
var a []int
a = append(a,10,20,30)
a = append(a,a...)
fmt.Println(a)
}

错误处理error

Go语言引入了一个关于错误处理的标准模式,即error接口,该接口的定义如下:

type error interface {
Error() string
}

1.初始化失败,退出

2.重试,比如if err !=nil,重试3次

3.异常上抛

package main

import "fmt"

func print() {
var p *int
fmt.Println(*p)
} func main() { defer func() {
err := recover()
fmt.Println(err)
}()
panic("不想执行下去了") //print()//1.空指针引用错误 //var n int
//fmt.Println(10 / n) //2.除数为0 /*
var i=3
var slice [3]int
fmt.Println(slice[i])//3.下标越界
*/
}

EOF error

recover.go:

Go语言引入了两个内置函数panic()和recover()以报告和处理运行时错误和程序中的错误场景:

当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用panic()函数时传入的参数,这个过程称为错误处理流程。

recover()函数用于终止错误处理流程。一般情况下, recover()应该在一个使用defer关键字的函数中执行以有效截取错误处理流程。如果没有在发生异常的goroutine中明确调用恢复过程(使用recover关键字) ,会导致该goroutine所属的进程打印异常信息后直接退出。

package main

import (
"fmt"
"time"
) func test() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}() b:=0
a := 1/b
fmt.Println(a)
return
} func main() {
for {
test()
time.Sleep(time.Second)
}
}

panic.go

package main

import (
"fmt"
"time"
"errors"
)
func initConfig() (err error) {
return errors.New("init config failed")
}
err := initConfig()
if err != nil {
panic(err)
}
return
} func main() {
for {
test()
time.Sleep(time.Second)
}
}

递归

一个函数调用自己,就叫做递归。

package main

import (
"fmt"
"time"
) func recusive(n int) {
fmt.Println("hello golang", n)
time.Sleep(time.Second)
if n > 10 {
return
}
recusive(n + 1)
} func main() {
recusive(0)
}

递归实现阶乘和斐波那契数列:

package main

import (
"fmt"
"time"
) func factor(n int) int {
if n == 1 {
return 1
}
return factor(n-1) * n
} func fab(n int) int {
if n <= 1 {
return 1
}
return fab(n-1) + fab(n-2)
} func main() {
fmt.Println(factor(5))
for i := 0; i < 10; i++ {
fmt.Println(fab(i))
}
}

函数类型

package main

import "fmt"

func print1(){
fmt.Println("print1")
} func print2() {
fmt.Println("print2")
} func func1(n int) int {
return n+1
} func main() {
//变量是个筐,装这个变量类型的数据
//函数也是个筐,容器,装的函数
var f func()
f = print1
f()
f=print2
f() var flist [3]func(int) int
flist[0]=func1
m:=flist[0](10)
fmt.Println(m)
fmt.Println(flist[0](10))
}

加减乘除:

package main

import (
"fmt"
"os"
"strconv"
) func add(m, n int) int {
return m + n
} func sub(m, n int) int {
return m - n
} func comp(m,n int) int {
return m * n
} func div(m,n int) int {
return m/n
} func main() {
funcmap := map[string]func(int, int) int{
"+": add,
"-": sub,
"*":comp,
"/":div,
} m, _ := strconv.Atoi(os.Args[1])
n, _ := strconv.Atoi(os.Args[3]) f := funcmap[os.Args[2]]
if f != nil {
fmt.Println(f(m, n))
}
}

匿名函数

匿名函数是指不需要定义函数名的一种函数实现方式

在Go里面,函数可以像普通变量一样被传递或使用,这与C语言的回调函数比较类似。不同的是, Go语言支持随时在代码里定义匿名函数。

package main
import (
"fmt"
"strings"
)
func toupper(s string) string {
return strings.Map(func(r rune) rune {
return r - ('a' - 'A')
}, s)
} func main() {
f := func(x,y int) int {
return x + y
}
fmt.Println(f(1,2)) f1:=func(x,y int) int {
return x + y
}(1,3)
fmt.Println(f1) fmt.Println(toupper("hello"))
}

闭包

闭包:一个函数和与其相关的引用环境组合而成的实体

package main

import (
"fmt"
) func addn(n int) func(int) int {
return func(m int) int {
return m+n
}
} func main() {
f := addn(3)
fmt.Println(f(12))
}

生成器:

package main

import "fmt"

func iter(s []int) func() int {
var i = 0
return func() int {
if i >= len(s) {
return 0
}
n := s[i]
i += 1
return n
}
} func main() {
f := iter([]int{1, 2, 3})
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
}

GO开发[四]:golang函数的更多相关文章

  1. Javascript模式(第四章函数)------读书笔记

    一 背景 js函数的两个特点:1 函数是第一类对象(first-class object):2 函数可以提供作用域 1 函数是对象: 1 函数可以在运行时动态创建,还可以在程序执行过程中创建 2 可以 ...

  2. php中strstr、strrchr、substr、stristr四个函数用法区别

    php中strstr.strrchr.substr.stristr四个函数用法区别: php中strstr strrchr substr stristr这四个字符串操作函数特别让人容易混淆,常用的是s ...

  3. C#的百度地图开发(四)前端显示与定位

    原文:C#的百度地图开发(四)前端显示与定位 有了这些定位信息,那要如何在前端的页面上显示出来呢?这需要用到百度地图的JavaScript的API.下面是示例代码. 前端代码 <%@ Page  ...

  4. python全栈开发 生成器 :生成器函数,推导式及生成器表达式

    python 全栈开发 1.生成器函数 2.推导式 3.生成器表达式 一.生成器函数 1.生成器: 生成器的本质就是迭代器 (1)生成器的特点和迭代器一样.取值方式和迭代器一样(__next__(), ...

  5. golang函数学习笔记

    golang函数特点: a.不支持重载,一个包不能有两个名字一样的函数 b.函数是一等公民,函数也是一种类型,一个函数可以赋值给变量 c.匿名函数 d.多返回值   例子1 func add(a, b ...

  6. electron/nodejs实现调用golang函数

    https://www.jianshu.com/p/a3be0d206d4c 思路 golang 支持编译成c shared library, 也就是系统中常见的.so(windows下是dll)后缀 ...

  7. STC8H开发(四): FwLib_STC8 封装库的介绍和注意事项

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  8. Oracle数据库中调用Java类开发存储过程、函数的方法

    Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日  浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...

  9. iOS开发之----常用函数和常数

    介绍一下Objective-c常用的函数,常数变量 算术函数 [算术函数] 函数名 说明 int rand() 随机数生成.(例)srand(time(nil)); //随机数初期化int val = ...

随机推荐

  1. [置顶] android ListView包含Checkbox滑动时状态改变

    题外话: 在xamarin android的开发中基本上所有人都会遇到这个小小的坎,的确有点麻烦,当时我也折腾了好一半天,如果你能看到这篇博客,说明你和我当初也是一样的焦灼,如果你想解决掉这个小小的坎 ...

  2. vue2 vue-rout

    vue 2.0的路由比起1.0简单了许多,分为以下几个步骤: 1.创建路由块和视图块: to里面是要切换的路径名称 <div id="app"> <div> ...

  3. IT服务(运维)管理实施的几个要点--序言

    IT服务(运维)管理(不是IT运维技术)是IT行业当中相对比较"窄"的一个分支,通常只被金融.电信等大型数据中心的中高层管理人员所关注.但是根据笔者多年从事IT服务和服务管理的经验 ...

  4. lesson - 6 课程笔记

    一.df  作用:  显示磁盘分区上的可使用的磁盘空间, 默认显示单位为kb . 可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间的等信息. 选项: -a :包含全部的文件系统 -h :以 ...

  5. python 爬去拉钩测试招聘信息

    代码如下: #coding:utf-8 import time import urllib.request from bs4 import BeautifulSoup file=open(r'meit ...

  6. u3d之世界坐标系,屏幕坐标系,视口坐标系,如何获取物体距离摄像机的距离

    世界坐标系就是unity的左手坐标系 屏幕坐标系是Game视图相机拍摄的场景坐标系,左下角(0,0),右上角(Screen.width,Screen.height),单位是像素.Z的位置是以相机的世界 ...

  7. 解决SVN造成的桌面图标问号

    之前不小心直接将版本库 的内容检出 到桌面,后才发现桌面上的文件 都变成了问号,本来也以为没有多大问题,删除.svn 即可,可是删除所有的.svn后,桌面上还是显示问号,刷新了很多次,还重启电脑 了, ...

  8. SQL基础学习_01_数据库和表

    SQL语句及其种类 1. SQL语句分为三类:     DDL(Data Definition Language): CREATE.DROP.ALTER;     DML(Data Manipulat ...

  9. DBA 优化法则

    硬件资源是根本,DBA是为了充分利用硬件资源:(更新中--) 统一SQL语句: 减少SQL嵌套: 执行计划返回结果集(决定计划走向): 合理使用临时表: tempdb分多文件: OLTP 条件使用变量 ...

  10. [js高手之路] es6系列教程 - 新的类语法实战选项卡

    其实es6的面向对象很多原理和机制还是ES5的,只不过把语法改成类似php和java老牌后端语言中的面向对象语法. 一.用es6封装一个基本的类 class Person{ constructor( ...