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 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。