0
package main

import (
    "fmt"
)

type test struct {
    Name string
}

func main() {
    foo := []test{
        {Name: "a"},
        {Name: "b"},
    }
    var bar []*test
    for _, item := range foo {
        fmt.Printf("%v\n", item.Name)
        bar = append(bar, &item)
    }
    
    for _, item := range bar {
        fmt.Printf("%v\n", item.Name)
    }
}

When I run the code above, I expect to see the output

a
b
a
b

However, the output is

a
b
b
b

What's going on?

For reference, this was done in the go playground

Spirit_Coffee
  • 63
  • 2
  • 6

1 Answers1

1

Golang src

// len_temp := len(range)
// range_temp := range
// for index_temp = 0; index_temp < len_temp; index_temp++ {
//     value_temp = range_temp[index_temp]
//     index = index_temp
//     value = value_temp
//     original body
//   }

Range is actually a syntax sugar for the for loop. Internally it still uses a for loop and it will first copy all the elements of the array and loop through them and assign each index and value to a temp variable. When retrieving the address of the value, it actually takes the address of the temp variable and the new array would actually has every element points to the same address.

To fix

for i, _ := range foo {
    p := foo[i]
    fmt.Printf("%v\n",  p.Name)
    bar = append(bar, &p)
}
kozmo
  • 4,024
  • 3
  • 30
  • 48