当前位置:首页 > 数据库

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

本篇问题:Go 中闭包的变量底层原理?

关于 defer 的基本知识点,我在以前的快照况教程中有写过:14. Go语言流程控制:defer 延迟调用

其中有一个知识是 defer 的变量快照,举个简单的什情失效例子来说

在下面这段代码中,会先打印出来 18,变量即使后面 age 已经被改变了,快照况可 defer 中的什情失效 age还是 修改之前的 0,这种现象称之为变量快照。变量

func func1() {      age := 0     defer fmt.Println(age) // output: 0     age = 18     fmt.Println(age)      // output: 18 } func main() {      func1() } 

对于这个输出结果,快照况相信还是什情失效挺容易理解的。

接下来,变量我请大家再看下面这个例子,快照况可以猜猜看会输出什么?什情失效

func func1() {      age := 0     defer func() {          fmt.Println(age)     }()     age = 18     return } func main() {      func1() } 

正确的答案是:18, 而不是变量 0

你肯定会纳闷:不对啊,defer 不是站群服务器快照况会对变量的值做一个快照吗?答案应该是 0 啊,为什么会是什情失效 18?

实际上,仔细观察,可以发现上面的两个例子的区别就在于,一个 defer 后接的是单个表达式,另一个 defer 后接的是一个函数,并且不是普通函数,而是一个匿名的闭包函数。

根据闭包的特性,实际上在闭包函数存的是 age 这个变量的指针(原因可以查看上一篇文章:Go 面试题 013:Go 中闭包的底层原理是网站模板?),因而,在 defer 后所修改的值会直接影响到 defer 中的 age 的值。

总结一下:

若 defer 后接的是单行表达式,那defer 中的 age 只是拷贝了 func1 函数栈中 defer 之前的 age 的值; 若 defer 后接的是闭包函数,那defer 中的 age 只是存储的是 func1 函数栈中 age 的指针。

本文转载自微信公众号「Go编程时光」,可以通过以下二维码关注。转载本文请联系Go编程时光公众号。

分享到:

滇ICP备2023006006号-16