Reputation: 4202
I do not understand why following program prints 0 1 2
. I thought it will print 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()
}
}
My reasoning of it should print 2 2 2
is that each run of the for loop shared the same scope(e.g., 2nd run of for loop does not terminate the scope of 1st run, the scope are shared). Thus idx's reference is shared by the anonymous function created with in each run of for loop. Thus when the loop ends, all 3 functions created shared the same reference of idx, whose value is 2.
So I think the question boils down to: Does a new run (e.g., i == 2) of for loop ends the scope of last run (e.g., i == 1) of for loop? Would appreciate if answer would point me to golang spec. (I could not find the spec mentioning this).
Upvotes: 1
Views: 51
Reputation: 8490
From spec https://golang.org/ref/spec#For_statements
A "for" statement specifies repeated execution of a block.
each of those blocks has its own scope and they are not nested or shared. But
Each "if", "for", and "switch" statement is considered to be in its own implicit block.
so variable i in your snippet is shared and
for i := 0; i < 3; i++ {
funcs = append(funcs, func() { fmt.Println(i) })
}
for _, f := range funcs {
f()
}
will print 3 3 3 as expected.
Upvotes: 2