tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

【go】funcの引数にstructの値渡し、ポインタ渡ししたときの挙動メモ

はじめに

goをなんとなく書き始めて半年経っていないくらいですが、
Goでxxxのポインタを取っているプログラムはだいたい全部間違っている という記事を見てなるほどなーと思いました。

最初のころとか確かに何となく無駄にポインタで渡していた気がする…

と、思ったところで、structについても自分で再確認するかーと思ったので
funcの引数にstructの値渡しとポインタ渡しで挙動を確かめてみるだけのgo初心者メモ

ソース

structを値として渡す場合とポインタとして渡す場合のいくつかだけの単純サンプル

package main

import "log"

type Data struct {
  Name string
  Age  int64
}

// #1.
//   arg :値渡し
//   処理:値のままプロパティアクセスして代入
func changeNameArgNormalAccessNormal(d Data) {
  d.Name = "fuga"
}

// #2.
//   arg :値渡し
//   処理:ポインタにしてからプロパティアクセスして代入
func changeNameArgNormalAccessPointer(d Data) {
  dPointer := &d
  dPointer.Name = "fuga"
}

// #3.
//   arg :ポインタ渡し
//   処理:値にしてからプロパティアクセスして代入
func changeNameArgPointerAccessNormal(dPointer *Data) {
  d := *dPointer
  d.Name = "fuga"
}

// #4.
//   arg :ポインタ渡し
//   処理:ポインタのままプロパティアクセスして代入
func changeNameArgPointerAccessPointer(dPointer *Data) {
  dPointer.Name = "fuga"
}

func main() {
  // #1
  d1 := Data{Name: "hoge", Age: 20}
  changeNameArgNormalAccessNormal(d1)
  log.Printf("d1: %+v", d1)

  // #2
  d2 := Data{Name: "hoge", Age: 20}
  changeNameArgNormalAccessPointer(d2)
  log.Printf("d2: %+v", d2)

  // #3
  d3 := Data{Name: "hoge", Age: 20}
  changeNameArgPointerAccessNormal(&d3)
  log.Printf("d3: %+v", d3)

  // #4
  d4 := Data{Name: "hoge", Age: 20}
  changeNameArgPointerAccessPointer(&d4)
  log.Printf("d4: %+v", d4)
}

https://github.com/tweeeety/go-struct-ref-sample

結果

#4 だけが元のコードの結果も変わります。
まぁ、そうだよね、というくらいでした。

$ go run struct_ref.go 
2017/06/21 23:53:22 d1: {Name:hoge Age:20}
2017/06/21 23:53:22 d2: {Name:hoge Age:20}
2017/06/21 23:53:22 d3: {Name:hoge Age:20}
2017/06/21 23:53:22 d4: {Name:fuga Age:20}

おわり

最初のころmapあたりは無駄にポインタにしたことがある気もしなくもない\(^o^)/