問題
User
構造体のintroduction
をIntroduction
構造体に代入しようとしたら、全て一番最後のプロパティの値が代入されてしまった
ソースコード
package main
import "fmt"
type User struct {
name string
age int
introduction string
}
type Introduction struct {
introduction *string
}
func main() {
users := []User{
{"Alice", 25, "Hello, I'm Alice!"},
{"Bob", 30, "Hi there, I'm Bob."},
{"Charlie", 22, "Greetings! I'm Charlie."},
}
introductions := makeIntroductions(users)
for _, introduction := range introductions {
fmt.Println(*introduction.introduction)
}
}
func makeIntroductions(us []User) []Introduction {
var introductions []Introduction
for _, user := range us {
introductions = append(introductions, Introduction{
introduction: &user.introduction,
})
}
return introductions
}
期待した結果
Hello, I'm Alice!
Hi there, I'm Bob.
Greetings! I'm Charlie.
出力結果
Greetings! I'm Charlie.
Greetings! I'm Charlie.
Greetings! I'm Charlie.
原因
introductions
の要素全てのポインタ(参照先)が同じだった
問題の箇所
for _, user := range us {
introductions = append(introductions, Introduction{
introduction: &user.introduction,
})
}
for range
において代入される要素の値は全て同じメモリ空間を使用します
そして今回introductions
にはそのポインタを代入しています
for _, introduction := range introductions {
fmt.Println(introduction.introduction)
}
0x140000740d8
0x140000740d8
0x140000740d8
つまり、最終的に出力される値も参照元が全て同じ値であるためfor range
で代入された一番最後値が結果として出力されたのです
対処法
for range
の要素がすべて同じメモリ空間で使用されないようにするため、for range
の中で代入される要素を新しい変数定義する
for _, user := range us {
introduction := user.introduction
introductions = append(introductions, Introduction{
introduction: &introduction,
})
}