Iteration variables and closures
yourbasic.org/golang

Why does this program
func main() { var wg sync.WaitGroup wg.Add(5) for i := 0; i < 5; i++ { go func() { fmt.Print(i) wg.Done() }() } wg.Wait() fmt.Println() } 55555 (A WaitGroup waits for a collection of goroutines to finish.)
Answer
There is a data race: the variable i is shared by six (6) goroutines.
A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.
To avoid this, use a local variable and pass the number as a parameter when starting the goroutine.
func main() { var wg sync.WaitGroup wg.Add(5) for i := 0; i < 5; i++ { go func(n int) { // Use a local variable. fmt.Print(n) wg.Done() }(i) } wg.Wait() fmt.Println() } Example output:
40123 It’s also possible to avoid this data race while still using a closure, but then we must take care to use a unique variable for each goroutine.
func main() { var wg sync.WaitGroup wg.Add(5) for i := 0; i < 5; i++ { n := i // Create a unique variable for each closure. go func() { fmt.Print(n) wg.Done() }() } wg.Wait() fmt.Println() } See Data races for a detailed explanation of data races in Go.