英文:
why local variable is different parameter at anonymous function in goroutine
问题
你好!以下是你提供的代码的中文翻译:
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
fmt.Println(runtime.GOMAXPROCS(0))
// s := "hello world \n"
for i := 0; i < 100; i++ {
go func(n int) {
fmt.Println(n, i)
}(i)
}
fmt.Scanln()
}
我只提供代码的翻译,不回答关于翻译的问题。
英文:
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
fmt.Println(runtime.GOMAXPROCS(0))
// s := "hello world \n"
for i := 0; i < 100; i++ {
go func(n int) {
fmt.Println(n, i)
}(i)
}
fmt.Scanln()
}
I just wondering why n
is not equal to i
every go routine.
Also i
sometimes has the same value as in the previous call.
What is the matter in this code?
答案1
得分: 9
这个主题已经有很多人讨论过(涉及多种语言),但简单来说就是这样的:
你当前的输出是这样的:
1 100
2 100
3 100
4 100
...
变量 i
成为闭包的一部分。这意味着它的值实际上超出了它的作用域(它被移动到一边,以便当 goroutine 执行时知道在哪里找到 i
)。
当调度器开始执行你的 goroutine 时,for
循环已经结束,i
的值将会是 100(如果你在一台慢机器上运行,可能会接近 100)。
修复的方法是在每次迭代中存储该值并使用它:
for i := 0; i < 100; i++ {
x := i // <------ 在每次循环迭代中存储 i 的值
go func(n int) {
fmt.Println(n, x) // <---- 使用新的、局部的、闭包的值,而不是主闭包的值
}(i)
}
现在每个 goroutine 引用自己的闭包变量 x
的副本,输出变为:
1 1
2 2
3 3
4 4
...
这种现象不仅仅局限于 Go 语言。
你可以在 Playground 上看到一个可运行的示例:
在 Playground 上查看
英文:
This topic is well covered (across multiple languages) - but the short version is this:
Your current output is like this:
1 100
2 100
3 100
4 100
...
The variable i
becomes part of a closure. This means that its value actually outlasts its scope (its moved off to the side so that when the goroutine executes it knows where to find i
).
By the time the scheduler gets around to executing your goroutines, the for
loop has finished and the value of i
is going to be 100 (or close to it if you're running on a slow machine).
The fix is to store the value every iteration and use that:
for i := 0; i < 100; i++ {
x := i // <------ Store the value of i each loop iteration
go func(n int) {
fmt.Println(n, x) // <---- Use the new, local, closed over value, not the main closed over one
}(i)
}
Now every goroutine references its own copy of a closed over variable x
, and your output becomes:
1 1
2 2
3 3
4 4
...
This phenomenon is not isolated to Go.
You can see a working sample on the playground:
<kbd>View it on the Playground</kbd>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论