The thing is that the iterator variable is allocated only once and the value it points to is changed with each iteration of the loop:
package main
import (
"fmt"
)
type A struct {
a *string
}
func f() {
slist := []string{"a", "b", "c"}
list := make([]*A, len(slist))
// v is only allocated once and the value at it's address is changed
// on each iteration.
for i, v := range slist {
fmt.Printf("Iteration %d: address of v %#v, value of v \"%s\"\n", i+1, &v, v)
// Add in a temp variable, which will get allocated
// and hence have a new address each iteration.
t := v
// Now assign that temp variable's address to the Item's a.
list[i] = &A{
a: &t,
}
}
fmt.Printf("[%s %s %s]", *list[0].a, *list[1].a, *list[2].a)
}
func main() {
f()
}
Run on playground
However, I have a strong feeling that this is unintuitive because we are pretty much talking of premature optimization. (A bit simplified): A string in Go is basically a slice of bytes([]byte
), with a slice already being a pointer to the backing array. See Go Slices: usage and internals for details.