不应该编译器捕获for...range
循环变量作为本地分配的闭包变量吗?Go中的捕获闭包(用于循环变量)
长的版本:
这引起了我的一些混乱in C#也和我试图去理解它;那为什么它在C#中修复了foreach
(原因是:循环变量不能修改在循环体内部)以及不修复它的原因C#for
循环(原因:循环变量可以修改循环)。
现在(我)在Go for...range
循环似乎在C#很像foreach
循环,但尽管我们不能改变这些变量(如k
和for k, v := range m { ... }
v
);我们仍然必须首先将它们复制到一些本地关闭,以使它们按预期行事。
这是什么原因? (我怀疑这是因为Go以同样的方式对待任何for
循环;但我不确定)。
下面是一些代码来检查描述的行为:
func main() {
lab1() // captured closure is not what is expected
fmt.Println(" ")
lab2() // captured closure is not what is expected
fmt.Println(" ")
lab3() // captured closure behaves ok
fmt.Println(" ")
}
func lab3() {
m := make(map[int32]int32)
var i int32
for i = 1; i <= 10; i++ {
m[i] = i
}
l := [](func() (int32, int32)){}
for k, v := range m {
kLocal, vLocal := k, v // (C) captures just the right values assigned to k and v
l = append(l, func() (int32, int32) {
return kLocal, vLocal
})
}
for _, x := range l {
k, v := x()
fmt.Println(k, v)
}
}
func lab2() {
m := make(map[int32]int32)
var i int32
for i = 1; i <= 10; i++ {
m[i] = i
}
l := [](func() (int32, int32)){}
for k, v := range m {
l = append(l, func() (int32, int32) {
kLocal, vLocal := k, v // (B) captures just the last values assigned to k and v from the range
return kLocal, vLocal
})
}
for _, x := range l {
k, v := x()
fmt.Println(k, v)
}
}
func lab1() {
m := make(map[int32]int32)
var i int32
for i = 1; i <= 10; i++ {
m[i] = i
}
l := [](func() (int32, int32)){}
for k, v := range m {
l = append(l, func() (int32, int32) { return k, v }) // (A) captures just the last values assigned to k and v from the range
}
for _, x := range l {
k, v := x()
fmt.Println(k, v)
}
}
因为它在lab1
所示,在评论// (A)
我们得到的只是来自range
最后一个值;输出就像是打印9,9
十次而不是显示预期的结果,如1,1
,2,2
,...(当然地图不一定在Go中排序,因此我们可能会看到3,3
是最后一对值的十倍;而不是10,10
作为最后一对值的十倍)。代码// (B)
处的代码lab2
也是如此,因为我们试图捕获内部作用域内的外部变量(我只是为了尝试这个)而捕获外部变量。在lab3
处注释代码// (C)
一切工作正常,你会十岁了数对那里像1,1
,2,2
,....
我试图用关闭+功能作为替代元组小号在Go。
你能否让你的例子更简洁明了?也许是因为这是半夜的事实,但我不能看到你的期望和你的例子中发生了什么。 – 2014-11-01 21:14:44
我已经描述了代码和我用这种方式编写它的目的,并遇到了这个问题。 – 2014-11-01 21:38:37
这是一个常见问题:https://golang.org/doc/faq#closures_and_goroutines – dyoo 2014-11-01 23:07:34