go学习笔记3
defer:defer的功能是将它修饰的代码或者代码块延迟执行,推迟到当前函数的结束,并且如果有多行被defer,会倒序执行。
fmt.println("start") defer fmt.println(1) defer fmt.println(2) defer fmt.println(3) fmt.println("end")
这段代码的输出是
start end 3 2 1
除过单行,defer也可以修饰匿名函数
defer func()int{
fmt.println(1)
fmt.println(2)
fmt.println(3) //内部是顺序执行
return 3
}() //别忘了立即执行
defer的效果是把代码推迟到return之后才执行。但是,对于”匿名函数立即执行“修饰defer,则分两种情况:
如果返回值没有提前命名:
func f1() int{ var a int //0 defer func(){ a++ }() //立即执行标记,但是受defer影响 return a //还是0 }
但是,如果命名返回值,匿名函数就可以影响返回值
func f2() (a int){ //命名了返回值 a = 0 defer func(){ a++ }() //立即执行, 也影响了外侧值 return a //1 不写a也行 }
go的return语句不是原子操作。不提前声明返回值,a就会立即被拷贝作为返回值传出,后续才执行的defer影响不到。如果提前声明了,那么a就是栈变量,defer可以直接影响到。

此外,defer修饰函数时,虽然函数会被推迟,但函数参数都要立即确定,也就是冻结了当前值,后续的影响不改变函数。
i :=0 defer fmt.println(i) //虽然defer,但打印0,不是1 i++
再据这个例子:

对于两个defer,注册顺序是先上后下,执行顺序则是先下后上。
由于注册是从上到下,而注册时延迟函数的参数都要确定。
所以calc("A",x,y)先执行 。 打印A 1 2 3
然后是calc("B",x,y) 打印 B 10 2 12
然后是执行顺序,calc("BB",x,calc("B",x,y)) 打印BB 10 12 22
最后是calc("AA",x,calc("A",x,y)) 打印AA 1 3 4
注意目前提到的都是值类型,切片等引用类型还会有区别
------- -------
panic和recover,panic可以在任何地方抛出异常,在同函数内靠前位置defer一个匿名函数,用一个变量承接recover()如果没报错那err就是nil。

go有errors这个包,此外error本身也是一个类型
浙公网安备 33010602011771号