1

为什么会这样:

for i := 0; i < 3; i++ {
    go func(i int) {
        fmt.Printf("%d", i)
    }(i)
}

打印 012

而这:

for i := 0; i < 3; i++ {
    go func() {
        fmt.Printf("%d", i)
    }()
}

打印 333?

4

2 回答 2

3

虽然 goroutine 很便宜,但它们并不是免费的。创建它们有一些但很少的开销。

在您的第一个程序中, 的值i被保留到 goroutine 中,因为您将它作为参数传递。(此时,每个 goroutine 都有自己的i' 值副本。)

在您的第二个程序中,i在第一个 goroutine 开始之前, 的值已经是 3。请记住,Go 程序中的 goroutine 共享相同的内存空间,因此在这种情况下,每个 goroutine 在i打印出来时都是相同的。

于 2013-08-11T05:56:10.637 回答
2

在你的循环之后添加一个打印语句for应该会让你清楚。你会看到 print 语句在你的 goroutine 函数之前运行。

当你在一个for循环中所做的只是启动一个新的 goroutine 时,你的循环通过非常快,并且通常甚至在你的第一个 goroutine 开始之前就完成了。因此,当您的 goroutine 启动时,您的循环已经完成并且 if 的值i3。记在脑子里。

当您将i作为函数参数传递时,就像您在第一个示例中所做的那样,它的当前值被复制到函数堆栈,因此函数将其当前值作为参数接收。这就是为什么你会看到012。但是,当闭包函数仅在其周围范围内使用变量时,就像您在第二个示例中所做的那样,它会在运行时访问其当前值,在您的情况下,这是在循环完成并i达到3.

您可以使用以下代码看到此效果:

for i := 0; i < 3; i++ {
    go func(arg int) {
        fmt.Printf("%d %d\n", arg, i)
    }(i)
}

产生这个输出:

0 3
1 3
2 3
于 2013-08-11T07:53:43.267 回答