user892960
user892960

Reputation: 309

How to iterate over channel and assign as reference

It seems assigning channel output to an array of pointers will always assign the last one sent to the channel string2. can anyone explain this behavior?

package main

import (
    "fmt"
)

type myType struct {
    myString string
}

func main() {
    queue := make(chan myType, 2)
    queue <- myType{myString: "string1"}
    queue <- myType{myString: "string2"}
    close(queue)

    var types []*myType

    for element := range queue {
        types = append(types, &element)
    }

    for _, element := range types {
        fmt.Println(element.myString)
    }
}

results in:

result2
result2

Upvotes: 0

Views: 346

Answers (1)

tkausl
tkausl

Reputation: 14279

This has nothing to do with channels. Check this code which has the same result:

package main

import (
    "fmt"
)

type myType struct {
    myString string
}

func main() {
    in := [2]myType{
        myType{myString: "string1"},
        myType{myString: "string2"},
    }

    var types []*myType

    for _, element := range in {
        types = append(types, &element)
    }

    for _, element := range types {
        fmt.Println(element.myString)
    }
}

Play

The problem is that you're taking a pointer to element, a variable which will get a new value each time through the loop, but the variable itself stays the same, so all pointers you append to the slice point to the same value. To fix this, append values instead of pointers or create a temorary in your loop and push a pointer to the temporary instead

var types []myType

for element := range queue {
    types = append(types, element)
}

or

var types []*myType

for element := range queue {
    tmp := element
    types = append(types, &tmp)
}

Upvotes: 3

Related Questions