Reputation: 157
Does anybody know why the case1 output the same result, but the case2 output the sequential result? I know the reason why case1 output the same value is that the closure of each function in functions slice access to the same scope.
But why after adding i:=i in each loop can case2 output the sequential result? Does after redefining i in eachloop, a new scope is generated? like let in javascript?
case1
func main() {
funcs := []func() {}
for i:=0;i<10;i++{
funcs = append(funcs, func() {
fmt.Println(i)
})
}
for i:=0;i<10;i++{
funcs[i]()
}
}
output
10
10
10
10
10
10
10
10
10
10
case2
func main() {
funcs := []func() {}
for i:=0;i<10;i++{
i := i
funcs = append(funcs, func() {
fmt.Println(i)
})
}
for i:=0;i<10;i++{
funcs[i]()
}
}
output
0
1
2
3
4
5
6
7
8
9
Upvotes: 0
Views: 74
Reputation: 26
This isn't really a scope issue but rather an issue with how the compiler decides if your variable i
is captured by reference or by value. This is not always obvious. For loops in go reuse the iteration variable in this case the i
. In case1 the variable i
is captured as a reference as the compiler sees it as being changed after the capture has taken place. In case2 the inner variable i
is created before the capture, captured and released thus the compiler sees it as unchanging and captures it by value. The result is when the functions are run in case1 the results are all the final value as that is what the variable i
ended up as and each function only holds a reference to that particular i
. In case2 each capture was passed a "copy" of i
at the time of creation thus they show the values you expect.
Upvotes: 1