Passing a pointer inside a loop with anonymous go functions causes only last element pointer to be used

StackOverflow https://stackoverflow.com/questions/23637099

  •  21-07-2023
  •  | 
  •  

Question

So in the following code I'm passing pointers to anonymous go functions but the code is not behaving as I am expecting it to do.

package main

import "fmt"

type (
    Element struct{
        Name string
    }
)

func main() {
    elements := []Element{{"first"}, {"second"}, {"third"}, {"fourth"}}
    waiting := make(chan bool)

    for _, element := range elements {
        go func(element *Element){
            fmt.Println("Element Name: ", element.Name)
            waiting <- true
        }(&element)
    }

    for i := 0; i < 4; i++{
        <- waiting
    }
}

I expected the code to write:

  • 'first'
  • 'second'
  • 'third'
  • 'fourth'

in any order but instead it is printing:

  • 'fourth'
  • 'fourth'
  • 'fourth'
  • 'fourth'

So it seems as the anonymous go function 'resolves' it's *Element parameter to whatever was in that loop at that time, so this code would be fixed by passing the Element{} itself instead of the pointer to the element.

My question is:

  • Is this defined behaviour?
  • How could i rewrite this to accept pointers to my Element{}?

Playground:

http://play.golang.org/p/tcRvforQE4

Edit: question formatting

Was it helpful?

Solution

What happens is that the for loop places the value of elements[i] in the same element variable for each iteration, not creating a new one. This means that &element is always the same address (try printing it before calling the function!)

A simple solution would be to just pass it a pointer to the actual memeber of the slice:

for i := range elements {

    go func(element *Element){
        fmt.Println("PostStream: ", element.Name)
        waiting <- true
    }(&elements[i])
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top