.vimrc
我只是想知道为什么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()
}
不等于n
每个例程。
i
有时与前一次通话中的值相同。
此代码中的问题是什么?
答案 0 :(得分:5)
这个主题很好地涵盖了(跨多种语言) - 但简短的版本是:
您当前的输出是这样的:
1 100
2 100
3 100
4 100
...
变量i
成为闭包的一部分。这意味着它的值实际上超出了它的范围(它移到了一边,这样当goroutine执行时它知道在哪里找到i
)。
当调度程序开始执行你的goroutine时,for
循环已经完成,i
的值将变为100(或者如果你正在运行则接近它在慢机器上。)
修复是每次迭代都存储值并使用:
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)
}
现在每个goroutine引用它自己的封闭变量x
的副本,输出变为:
1 1
2 2
3 3
4 4
...
这种现象并不孤立于Go。
你可以在操场上看到一个工作样本: View it on the Playground