Rohan
Rohan

Reputation: 7976

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

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:

in any order but instead it is printing:

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:

Playground:

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

Edit: question formatting

Upvotes: 4

Views: 1131

Answers (1)

Not_a_Golfer
Not_a_Golfer

Reputation: 49195

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])
}

Upvotes: 8

Related Questions