为什么局部变量是goroutine中匿名函数的不同参数

时间:2015-12-04 02:42:02

标签: go goroutine

.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有时与前一次通话中的值相同。

此代码中的问题是什么?

1 个答案:

答案 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