Go defer如何调用
1、在defer语句声明时进行估值
我们都知道go中defer
是延时调用,一般在return语句结束后调用。但是如果defer语句中包含变量呢,那变量该如何计算?
看这样一个例子
|
|
请问该函数的输出是什么呢?1,2,3还是2,13?
其实结果是这样的:
|
|
解释下,其实是这样的,在执行代码12行的时候,编译器先进行了x.add(2)
的计算,然后进行.add(3)
的压栈操作。所以就出现了这样的结果,执行12行时对语句进行了估值,先输出了2
,紧接着执行13行,输出1
;最后执行defer
的出栈操作,输出3
。
我们在看这样一个例子:
|
|
与上面的例子不同的是,在结构体中增加了一个字段num。可以思考下这种情况的输出。
其结果是:
|
|
首先输出add 2 1
应该没有疑问,因为在执行15行的时候,先对x.add(2)
进行了估值;
紧接着输出inc 1
,因为在x.add(2)
中对num
进行了+1
操作;
然后执行defer函数.add(3)
,输出add 3 2
,此时num
又进行了一次+1
操作;
最后执行main函数,输出main 1
,为啥不是2呢,因为17行先返回。
那如果做一个小的修改,就inc
函数返回su
结构体指针,在main函数中查看其num值。应该得到main 2
。
修改后是这样的:
|
|
其输出结果是,符合预期。
|
|
在文章https://go.dev/blog/defer-panic-and-recover中,描述了defer语句的三个原则,其分别是:
1.A deferred function’s arguments are evaluated when the defer statement is evaluated.
即defer函数中的参数在defer语句声明时已经被估值。
所以像下面的写法,将输出0
。
|
|
- Deferred function calls are executed in Last In First Out order after the surrounding function returns.
这个比较好理解,defer函数的顺序满足 后入先出 的原则。
像下面的例子,将输出”3210“:
|
|
- Deferred functions may read and assign to the returning function’s named return values.
defer函数能够读取并对函数的命名返回值赋值
看下面这个例子,其结果是”main 2"
|
|
附录:
Defer,Panic,and Recover:https://go.dev/blog/defer-panic-and-recover
- 原文作者:Kevin
- 原文链接:http://www.subond.com/post/2022-09-26_golang_defer/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。