Skip to main content

函数

函数是一段可重复使用的代码段

go
1
2
3
4
func fn_name(params-list)(return-list){
body
}

在go语言中,函数的四要素:

函数名,

参数列表

返回值列表

函数体

与其他语言函数显著的不同点在于,go语言中的函数允许多个返回值.

函数名

没有函数名的函数称之为匿名函数,匿名函数通常用在只执行一次的场景.

函数递归

函数可以递归,这意味着函数可以直接或间接的调用自己,

go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
res := sum(100)
fmt.Println(res)
}
func sum(num int) int {
if num > 0 {
return num + sum(num-1)
} else {
return 0
}
}

思考,这种写法有什么弊端,若原函数名被修改,是否会造成不能找到原函数,该问题如何解决呢?

函数参数

go语言中的参数不支持默认值,多个相邻参数类型且相同时可进行简写

不定参数

所有函数的参数都是按照值进行传递的.

函数变量

在go语言中函数被设计为头等公民.

在变成语言设计中,一个实体如果支持所有通常对其他实体可用的操作,那么这个实体就被认为是一等公民,这些操作包括赋值给变量,作为参数传递,作为返回值返回.

将函数赋值给变量

go
1

更重要的是,以这种方式定义的函数能够获取到整个词法环境,因此里层函数可以访问外层函数中的变量,一直到当前文件的最外层,如果还是没有找到则会报错.

函数类型的零值是nil,调用一个空的函数变量将导致宕机.

作为参数传递给函数

作为返回值

匿名函数

命名函数只能在包级别作用域进行声明

函数参数

go语言中的函数参数不能设置默认值.

在函数定义时有形参,在调用函数时必须传递.

参数简写

多个相邻参数且类型相同时,可简化书写.

变长参数

经常使用的fmt.Println()为什么接收任意个参数呢?

go
1
2
3
4
func Println(a ...any) (n int, err error) {
return Fprintln(os.Stdout, a...)
}

在参数列表最后的类型名称钱使用省略号...,表示声明一个变长函数,调用这个函数的时候可以传递该类型任意数目的参数.

go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
res1 := sum(1, 2)
res2 := sum(1, 2, 3)
res3 := sum(1, 2, 3, 4, 5)
fmt.Println(res1, res2, res3)
}
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}

变长参数有且只能有一个,位于函数的最后一个参数.

变长参数在函数内是类似slice,在需要遍历的场景,可将其当作slice来用

需要注意的是变长函数的类型和一个带有普通slice参数的函数的类型是不同的.

函数的延迟调用--defer

通常用于关闭系统资源,

按照defer的注册顺序,先注册的后执行,类似于

defer后跟函数调用,或方法调用.

错误处理

panic,触发一个运行时错误,至到遇到recover或程序终止.