[Golang] Pass Reference to Goroutine While range Slice


Something strange happened when I tried to pass references to goroutines while range slice. Consider the following code:

package main

import (
      "fmt"
)

func printNumber(number *int, c chan int) {
      fmt.Println(*number)
      c <- 1
}

func main() {
      numbers := []int{1, 2, 3}

      c := make(chan int)
      for _, number := range numbers {
              go printNumber(&number, c)
      }

      // wait all goroutines to finish
      for i := 0; i < len(numbers); i++ {
              <-c
      }
}

Run Code on Go Playground

The output in the console is:

3
3
3

I cannot figure out what happened. It supposed to be something like:

1
3
2

But I got all 3! This is not what I want. I cannot figured out what's wrong, so I tried some googling [2], and the answer in [3] gived me solution.

Solution: use the array index instead of the value

Change the code of range to the following:

for index, _ := range numbers {
        go printNumber(&numbers[index], c)
}

Run Code on Go Playground

And now everything works as expected! (Although I still do not know why!)


Tested on:


References:

[1][Golang] Wait For Goroutine to Finish
[2]
[3]pointers - golang range references instead values - Stack Overflow