当前位置: > > > > 封闭所容纳的环境范围是什么?
封闭所容纳的环境范围是什么?
来源:stackoverflow
2024-04-25 13:42:34
0浏览
收藏
学习知识要善于思考,思考,再思考!今天米云小编就给大家带来《封闭所容纳的环境范围是什么?》,以下内容主要包含等知识点,如果你正在学习或准备学习Golang,就都不要错过本文啦~让我们一起来看看吧,能帮助到你就更好了!
问题内容
我模仿网上关于闭包的教程,写了下面的代码。
func foo1() func() {
xvalue := 1
x := &xvalue
defer func() {
xvalue = 2
}()
return func() {
*x = *x + 1
fmt.printf("foo1 val = %d\n", *x)
}
}
func main() {
f1 := foo1()
f1()
f1()
f1()
}
我很困惑,在执行 f1 := foo1() 后,变量 xvalue 似乎应该被回收,因此使用 *x 应该是错误的,但上面的代码没有错误并且执行罚款,给出输出
foo1 val = 3 foo1 val = 4 foo1 val = 5
所以我想知道闭包除了保存指针本身之外还保存了指针的值还是go语言的垃圾回收机制导致xvalue没有被删除?
正确答案
在 Go 中,闭包获取对其关闭的任何变量(的地址)的引用。引用:
函数文字是闭包:它们可以引用周围函数中定义的变量。然后,这些变量在周围的函数和函数文字之间共享,并且只要可访问,它们就会一直存在。
因此,在您的示例中:
-
f1 := foo1()- 使
xValue变量存在(编译器可能会在堆上分配它)。它将以其类型的零值 0 开始。 - 使变量
x存在并为其分配xValue的地址。 defer-red 闭包运行并将值 2 分配给xValue。- 返回一个关闭变量
x的闭包。
后一点可能有点棘手:由于返回的闭包引用了变量
x,编译器保证即使在foo返回后该变量也存在。由于x包含xValue的地址(因此是对它的实时引用),因此该地址仍然存在,并且不能被垃圾收集。 使用相同的转义分析方法,编译器保证xValue在其声明的函数返回后仍然存在。 - 使
-
您执行返回的闭包,该闭包通过指向它的指针修改
xValue– 这里没有发生任何魔法。另外两个调用执行相同的操作。
总而言之,也许您被 C++ 知识绊倒了,一旦从该函数返回控制权,函数中声明的任何变量都将不再存在,因此该函数外部存在的对该变量的任何引用都将变为无效的。在 Go 中,情况并非如此:在这方面,该语言被显式定义为安全:编译器确保任何变量都有适当的分配,以便在返回(或以其他方式传达)对它的引用时在创建它的函数调用中生存下来。从该函数调用到外部世界。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持米云!更多关于Golang的相关知识,也可关注米云公众号。
