Дело в том, что переменная итератора назначается только один раз, и значение, на которое она указывает, изменяется при каждой итерации цикла:
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()
}
Запуск на площадке
Однако у меня есть сильное чувство, что это не интуитивно понятно, потому что мы в значительной степени говорим о преждевременной оптимизации.(Немного упрощенно): Строка в Go - это, в основном, фрагмент байтов ([]byte
), причем фрагмент уже является указателем на массив поддержки.Подробнее см. Go Slices: использование и внутреннее оборудование .