函数
函数定义
函数名:由字母、数字、下划线组成。但函数名的第一个字母不能是数字。在同一个包内,函数名也称不能重名
调用有返回值的函数时,可以不接收其返回值。
可变参数
可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数名后加...来标识,可变参数通常要作为函数的最后一个参数。
eg: func function(x int,y ...string) int{}
变量作用域
全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。
局部变量又分为两种:
函数内定义的变量无法在该函数外使用。如果局部变量和全局变量重名,优先访问局部变量。
语句块定义的变量,通常会在if条件判断、for循环、switch语句使用这种定义变量的方式,这些变量只在for、if、switch中生效。
匿名变量
匿名函数因为没有函数名,所以没办法像普通函数那样调用,所以匿名函数需要保存到某个变量或者作为立即执行函数:
保存到某个变量:
add := func(x, y int) {
fmt.Println(x + y)
}
add(10, 20)
自执行函数:
func(x, y int) {
fmt.Println(x + y)
}(10, 20)
闭包
闭包指的是一个函数和与其相关的引用环境组合而成的实体。简单来说,闭包=函数+引用环境。
func calc(base int) (func(int) int, func(int) int) {
add := func(i int) int {
base += i
return base
}
sub := func(i int) int {
base -= i
return base
}
return add, sub
}
func main() {
f1, f2 := calc(10)
fmt.Println(f1(1), f2(2)) //11 9
fmt.Println(f1(3), f2(4)) //12 8
fmt.Println(f1(5), f2(6)) //13 7
}
defer语句
Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。
panic/recover
panic可以在任何地方引发,但recover只有在defer调用的函数中有效。
recover()必须搭配defer使用。
defer一定要在可能引发panic的语句之前定义。
eg:
func funcB() {
defer func() {
err := recover()
//如果程序出出现了panic错误,可以通过recover恢复过来
if err != nil {
fmt.Println("recover in B")
}
}()
panic("panic in B")
}
defer的机制
1.defer执行顺序为:先进后出(栈)
2. 当defer被声明时,其参数就会被实时解析
func f44() (r int) {
r = 2
defer func() {
r = r + 5
}()
return r
}//返回值为7
func f44() (r int) {
r = 2
defer func(r int) { //这里的r与返回值r不是同一个
r = r + 5 //这里的r与返回值r不是同一个
}()
return r
}//返回值为2