当前位置: 首页 > 科技观察

Defer的变量快照在什么情况下会失效?

时间:2023-03-15 01:37:38 科技观察

本题:Go中闭包的底层原理是什么?关于defer的基础知识,我在之前的教程里写过:14.Go语言流程控制:defer延迟调用,其中一个是deferSnapshot的变量,举个简单的例子,下面的代码中,会先打印18,即使后面修改了age,修改前defer中的age还是0,这种现象称为变量快照。funcfunc1(){age:=0deferfmt.Println(age)//output:0age=18fmt.Println(age)//output:18}funcmain(){func1()}这个输出结果,相信还是挺容易的了解。接下来请大家再看下面这个例子,大家猜猜会输出什么?funcfunc1(){age:=0deferfunc(){fmt.Println(age)}()age=18return}funcmain(){func1()}正确答案是:18,不是0。你一定想知道:不,不会不延迟拍摄变量值的快照吗?答案应该是0,为什么是18?其实仔细观察的话,可以发现上面两个例子的区别在于,一个defer后面跟着一个单独的表达式,另一个defer后面跟着一个函数,而且不是普通的函数,而是一个匿名闭包功能。根据闭包的特点,其实就是在闭包函数中保存了指向变量age的指针(原因可参考上一篇:Go面试题013:Go中闭包的底层原理是什么?),因此,经过defer修改后的值会直接影响defer中age的值。总结一下:如果defer后面跟的是单行表达式,那么defer中的age只是复制了func1函数栈中defer之前age的值;如果defer后面跟着一个闭包函数,那么defer中的age就是存放在func1函数栈中age的指针。本文转载自微信公众号“Go编程时间”,可通过以下二维码关注。转载本文请联系围棋编程时间公众号。