Iterating using a goroutine is giving unexpected result

Issue

I was doing some condition checking inside the goroutine based on the iteratating variable i and found that it is giving me results that I wasn’t expecting, and I decided to confirm it with some simple code.

    for i := 1; i <= 5; i++ {
    wg.Add(1)
    fmt.Println(i)

    go func() {
        fmt.Println(i)
        wg.Done()
    }()


}
wg.Wait()

1
2
3
4
5
6
6
6
6
6

Is this expected behaviour? Could someone kindly explain why is 6 being printed for 5 times, though I was iterating only till 5??

Solution

Playground example

All your goroutines are running asynchronously after your for loop has finished.

At the end of your for loop i is equal to 6, and thus, your goroutines each log the number 6.

To fix the problem you can create a closure, and save the current value of i inside it so that when the goroutine runs, it runs with the proper value of i.

To do this just change your code so it looks like

go func(x int) {
  fmt.Println(x)
  wg.Done()
}(i) // <--- "save" value of i at this point in time.

This way you “save” the value of i inside the function you’re telling the goroutine to execute such that later, when the for loop has run to completion, it doesn’t use the current value of i which is 6; instead, it uses the old value of i at the time the goroutine was created.

Answered By – m0meni

Answer Checked By – Terry (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.