3 回答
TA贡献1805条经验 获得超9个赞
这与返回闭包后变量如何封装在闭包中有关。考虑以下示例(播放中的实时代码):
func newClosure() func() {
i := 0
fmt.Println("newClosure with &i=", &i)
return func() {
fmt.Println(i, &i)
i++
}
}
func main() {
a := newClosure()
a()
a()
a()
b := newClosure()
b()
a()
}
运行此代码将产生类似于以下输出的内容。我注释了哪一行来自哪个语句:
newClosure with &i= 0xc010000000 // a := newClosure()
0 0xc010000000 // a()
1 0xc010000000 // a()
2 0xc010000000 // a()
newClosure with &i= 0xc010000008 // b := newClosure()
0 0xc010000008 // b()
3 0xc010000000 // a()
在示例中, 返回的闭包newClosure封装了局部变量i。这对应current于您的代码中的等。你可以看到它a并b 有不同的 实例i,否则调用b()会被打印出来3。您还可以看到i变量具有不同的地址。(该变量已经在堆上,因为 go 没有单独的堆栈内存,所以在闭包中使用它完全没有问题。)
因此,通过生成一个新的闭包,您会自动为该闭包创建一个新的上下文,并且局部变量不会在闭包之间共享。这就是为什么在循环中创建一个新的闭包不会让你走得更远的原因。
就本例而言,您的代码的等效项是:
for i:=0; i < 10; i++ {
newClosure()()
}
并且您已经从输出中看到这是行不通的。
- 3 回答
- 0 关注
- 212 浏览
添加回答
举报