💨

Go ポインタを使うケース

2021/05/08に公開

引数やレシーバを関数内で書き換えた結果を取得する必要がある場合

type N struct { value int }

func (n N) CopyAdd (v int) {
  n.value += v
}

func (n *N) PointerAdd (v int) {
  n.value += v
}

func main() {
  var n N
  n.CopyAdd(10)
  fmt.Println(n.value) // 0
  n.PointerAdd(10)
  fmt.Println(n.value) // 10
}

main関数内でn.valueを書き換えた結果を取得する場合、ポインターを使用しなければなりません。
この場合がポインタを使うケースとして真っ先に思いつくのではないのでしょうか。

大きな構造体かスライスの場合

基本的にポインタを使用すると、重い処理を伴う上に、ガーベージコレクションのオーバーヘッドが高くなります。
よって、プリミティブ型やフィールドが多くない構造体の場合はポインタを使用しない方が効率的です。

しかし、大きな構造体やスライスの場合は、ポインタ渡しの方がメモリコピー量を減らせるので、効率的です。

可読性

値が変更される可能性がある場合、ポインタを使用した方が読み手にとって分かりやすい場合があります。

コピーの生成を避けたい場合

func Open(name string) (file *File, err error) {
  return OpenFile(name, O_RDONLY, 0)
}

値渡しの場合、コピーが生成されますが、ファイルなどを扱う場合、コピーが生成されると問題があります。
問題がある場合、ポインターを使用することでコピーの生成を防ぐことができます。

プリミティブな値だがnilを許容する場合

上記とは異なるので例外にはなりますが、プリミティブ型でもnilを許容したい場合はポインタを使う場合があります。

Discussion