英文:
Enclosed Variable Overridden In Loop
问题
我正在尝试构建一个包含封闭变量(在这种情况下是一个字符串)的函数数组,但是我得到了一些意外的输出。我猜想我得到这个输出的原因是每次迭代后,被附加的函数文字实际上是一个指向正在更改的代码的指针。
有没有办法使用new()
或make()
创建一个函数类型,以便append()
在每次迭代时都获得一个不同的函数实例?
package main
import "log"
var functions []func()
func main() {
for _, s := range [...]string{"goodbye", "cruel", "world"} {
functions = append(functions, func() {
log.Println(s)
})
}
for _, f := range functions {
f()
}
}
输出:
2014/11/23 18:13:16 world
2014/11/23 18:13:16 world
2014/11/23 18:13:16 world
英文:
I am trying to build an array of functions that contain an enclosed variable (in this case a string) but I was getting some unexpected output. I figure the reason I am getting this output is because the func literal being appended is actually a pointer to code that is being changed after each iteration.
Is there a way to new()
or make()
a function type so that append()
will get a different function instance per iteration instead?
package main
import "log"
var functions []func()
func main() {
for _, s := range [...]string{"goodbye", "cruel", "world"} {
functions = append(functions, func() {
log.Println(s)
})
}
for _, f := range functions {
f()
}
}
Outputs:
2014/11/23 18:13:16 world
2014/11/23 18:13:16 world
2014/11/23 18:13:16 world
答案1
得分: 3
每次循环迭代都使用相同的变量s
实例,因此每个闭包共享该单个变量。为了将s
的当前值绑定到每个闭包中,需要修改内部循环以在每次迭代时创建一个新变量。例如,
package main
import "log"
var functions []func()
func main() {
for _, s := range [...]string{"goodbye", "cruel", "world"} {
s := s // 创建新的s
functions = append(functions, func() {
log.Println(s)
})
}
for _, f := range functions {
f()
}
}
输出:
2009/11/10 23:00:00 goodbye
2009/11/10 23:00:00 cruel
2009/11/10 23:00:00 world
参考资料:
What happens with closures running as goroutines?
Captured Closure (for Loop Variable) in Go
英文:
Each iteration of the loop uses the same instance of the variable s
, so each closure shares that single variable. To bind the current value of s
to each closure as it is launched, one must modify the inner loop to create a new variable each iteration. For example,
package main
import "log"
var functions []func()
func main() {
for _, s := range [...]string{"goodbye", "cruel", "world"} {
s := s // create new s
functions = append(functions, func() {
log.Println(s)
})
}
for _, f := range functions {
f()
}
}
Output:
<pre>
2009/11/10 23:00:00 goodbye
2009/11/10 23:00:00 cruel
2009/11/10 23:00:00 world
</pre>
References:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论