What should this code print?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| package main
import (
"fmt"
"sync"
)
func main() {
arr := []int {1, 2, 3}
var wg sync.WaitGroup
for i := 0; i < len(arr); i++ {
wg.Add(1)
// Start a thread to do some heavy work in the background
go func() {
fmt.Printf("i is %d\n", i)
wg.Done()
}()
}
// Wait till all the threads finish
wg.Wait()
}
|
Instead of printing
1
2
3
| i is 0
i is 1
i is 2
|
It generates
1
2
3
| i is 3
i is 3
i is 3
|
What happened?
Turns out that the reference to i is captured but not the value. So when the internal anonymous function runs, it gets the current value of i at the time of execution and not creation.
One general rule for this is to never access value from the outer function directly, instead pass those values as parameters.
Consider this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| package main
import (
"fmt"
"sync"
)
func main() {
arr := []int {1, 2, 3}
var wg sync.WaitGroup
for i := 0; i < len(arr); i++ {
wg.Add(1)
// Start a thread to do some heavy work in the background
go func(j int) {
fmt.Printf("i is %d\n", j)
wg.Done()
}(i) // Capture the value at the time of thread creation
}
// Wait till all the threads finish
wg.Wait()
}
|
And it produces
1
2
3
| i is 2
i is 0
i is 1
|