for循环的新运行是否结束了for循环的最后一次运行的范围?

时间:2016-08-31 22:30:11

标签: go scope

我不明白为什么跟随程序打印0 1 2。我以为会打印2 2 2

package main

import (
    "fmt"
)

func main() {
    var funcs []func()
    for i := 0; i < 3; i++ {
        idx := i
        funcs = append(funcs, func() { fmt.Println(idx) })
    }

    for _, f := range funcs {
        f()
    }
}

我应该打印2 2 2的原因是for循环的每次运行都共享相同的范围(例如,for循环的第二次运行不会终止第一次运行的范围,范围是共享的)。因此,idx的引用由for循环的每次运行中创建的匿名函数共享。因此,当循环结束时,创建的所有3个函数共享idx的相同引用,其值为2.

所以我认为这个问题归结为:for循环的新运行(例如,i == 2)是否结束了for循环的最后一次运行(例如,i == 1)的范围?如果答案能指向golang spec,我将不胜感激。 (我找不到提到这个的规格。)

1 个答案:

答案 0 :(得分:2)

来自规范https://golang.org/ref/spec#For_statements

  

A&#34; for&#34; statement指定重复执行一个块。

每个块都有自己的范围,它们不是嵌套的或共享的。但是

  

每个&#34; if&#34;,&#34; for&#34;,&#34;&#34; switch&#34;声明被认为是在其中   拥有隐含的阻止。

您的代码段中的变量i是共享的

for i := 0; i < 3; i++ {
        funcs = append(funcs, func() { fmt.Println(i) })
}

for _, f := range funcs {
        f()
}

将按预期打印3 3 3。