golang之defer
延迟调用函数defer的调用方式如下:
defer func_name(param_list)
- 执行的时机
func f1() (ret int) {
defer func() {
ret++
}()
return 0
}
func f2() (ret int) {
temp := 1
defer func() {
temp += 10
}()
return temp
}
func f3() (ret int) {
defer func(ret int) {
ret += 10
}(ret)
return 1
}
先不要运行程序,心里记下自己认为分别运行这三个函数的结果,然后我们慢慢分析。
这里我们不分析defer的底层机制,只需知道它的实现效果。由于return语句并不是原子操作,它是分为两步来执行的:
(1)先在栈中写一个值,这个值被当做返回值;
(2)然后调用空的return语句。
有了defer之后,defer的执行是被插入在return之前赋值指令之后的
有了这个结论之后,我们来分析之前的代码结果:
f1():先给需要返回的值ret赋值为0,然后执行defer,将ret++,最后执行return语句返回1;
f2():将初始的temp=1赋值给temp,然后执行defer,temp+=10,此时返回的ret并不受temp的影响,最终结果仍然为1;
f3():return之前,先执行ret=1的赋值操作,然后,将ret 值传递给匿名函数,执行的结果不影响之前的值,所以ret函数最终的返回值是1。
- 执行的顺序
func f4() {
defer func() {
fmt.Println("1-1")
defer func() {
fmt.Println("1-1-1")
}()
}()
defer func() {
fmt.Println("2-2")
defer func() {
fmt.Println("2-2-2")
}()
}()
}
结果如下:
可以看出它是基于先进后出的方式存储defer函数的,也就是逆序执行的。