Tommy's Blog

構造体のスライスを作るときは要素をポインタにする

Goで構造体のスライスを作るときは、構造体をそのまま要素にするのではなくポインタにしたほうが基本的には良さそう

コード例1

1つ目のfor-range文(という用語が正確かどうかはさておき)で、スライスの各要素である構造体が持つnameプロパティの値を変えています。
2つ目のfor-range文で、同じスライスの各要素を表示するというコードです。

  • 構造体のポインタを要素にしたとき(https://play.golang.org/p/RQIacjEfwNM)
    2回目のfor-range文で要素を表示したときには、1回目のfor-range文での変更が反映されています。直感的にそうだろうなと思える動作をしています。

  • 構造体を要素にしたとき(https://play.golang.org/p/rJPY0znHzPt)
    2回目のfor-range文では、要素が変更されていません。なぜかというと、下記のコードにおいて、変数pのスコープはfor文内部のみで有効で、pにはコピーされた構造体が入るからです。要はスライスの要素の構造体とpは別物だからです。
    理由自体は簡単ですが、動作としては直感的かと言われるとそうではなさそうです

for _, p := range people {
  p.name = "hoge"
}

コード例2

参考までに、引数に構造体のスライスを渡したときの例も載せておきます。(コード例1と大体同じ)