英文:
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论