package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
fmt.Println(runtime.GOMAXPROCS(0))
// s := "hello world
"
for i := 0; i < 100; i++ {
go func(n int) {
fmt.Println(n, i)
}(i)
}
fmt.Scanln()
}
I just wondering why n
is not equal to i
every go routine.
Also i
sometimes has the same value as in the previous call.
What is the matter in this code?
This topic is well covered (across multiple languages) - but the short version is this:
Your current output is like this:
1 100
2 100
3 100
4 100
...
The variable i
becomes part of a closure. This means that its value actually outlasts its scope (its moved off to the side so that when the goroutine executes it knows where to find i
).
By the time the scheduler gets around to executing your goroutines, the for
loop has finished and the value of i
is going to be 100 (or close to it if you're running on a slow machine).
The fix is to store the value every iteration and use that:
for i := 0; i < 100; i++ {
x := i // <------ Store the value of i each loop iteration
go func(n int) {
fmt.Println(n, x) // <---- Use the new, local, closed over value, not the main closed over one
}(i)
}
Now every goroutine references its own copy of a closed over variable x
, and your output becomes:
1 1
2 2
3 3
4 4
...
This phenomenon is not isolated to Go.
You can see a working sample on the playground: View it on the Playground