構造体の値のスライスとポインタのスライス、どちらがいいのか?
こんな構造体とJSON文字列を定義して…
type Hoge struct { Nyan int64 Wang string } const jsonStr = `[{"nyan":1, "wang":"aaaa"}, {"nyan":1, "wang":"bbbb"}]`
ポインタのスライスの場合
var a []*Hoge json.Unmarshal([]byte(jsonStr), &a) for i, h := range a { h.Nyan *= 2 h.Wang += h.Wang fmt.Println(h == a[i]) fmt.Println(*h == *a[i]) } fmt.Println(a[0].Nyan, a[0].Wang) fmt.Println(a[1].Nyan, a[1].Wang)
結果
2 aaaaaaaa 4 bbbbbbbb
ループの中での変更は反映される。まあポインタだから当然。
値の場合
var b []Hoge json.Unmarshal([]byte(jsonStr), &b) for _, h := range b { h.Nyan *= 2 h.Wang += h.Wang } fmt.Println(b[0].Nyan, b[0].Wang) fmt.Println(b[1].Nyan, b[1].Wang)
結果
1 aaaa 2 bbbb
ループの中での変更は反映されていない。つまりループ変数の h には構造体がコピーされて渡されているということ。巨大な構造体のスライスをループさせるとコピーの負荷がそれなりに発生しそう。特に理由がなければポインタのスライスにしたほうが良さそう。