こんなコードがあります
package main import "log" var ( yy []Hoge zz map[string]*Hoge = make(map[string]*Hoge) ) type Hoge struct { a int b int } func main() { d1 := Hoge{} d1.a = 10 d1.b = -20 zz["d1"] = &d1 yy = append(yy, d1) d2 := Hoge{} d2.a = 5 d2.b = -8 zz["d2"] = &d2 yy = append(yy, d2) log.Println("yy[0] = ", yy[0], "*zz[d1] = ", *zz["d1"]) log.Println("yy[1] = ", yy[1], "*zz[d2] = ", *zz["d2"]) yy[0].a = -9 yy[0].b = 888 yy[1].a = -6 yy[1].b = 444 // zzにも変更が反映されると思い込んでた log.Println("yy[0] = ", yy[0], "*zz[d1] = ", *zz["d1"]) log.Println("yy[1] = ", yy[1], "*zz[d2] = ", *zz["d2"]) }
コメントに書いたとおりなんですが、実行すると
2017/03/31 12:57:59 yy[0] = {10 -20} *zz[d1] = {10 -20} 2017/03/31 12:57:59 yy[1] = {5 -8} *zz[d2] = {5 -8} 2017/03/31 12:57:59 yy[0] = {-9 888} *zz[d1] = {10 -20} # yyへの変更がzzには 2017/03/31 12:57:59 yy[1] = {-6 444} *zz[d2] = {5 -8} # 反映されてくれない
途中でyyに与えた変更がzz側にも波及することを期待してたのですが、zzに保持されてるポインタは冒頭で定義した一時変数(のつもり)のd1/d2のポインタなのでソチラ側への変更が反映されてる、と。(しかも、d1/d2をzzが参照してるからGCで回収されないはず。。。)
期待通りに動かそうと思うと、格納してるポインタをd1/d2のものからyy[0]/yy[1]のものに直せば良いと言えば良いのですが
func main() { d1 := Hoge{} d1.a = 10 d1.b = -20 yy = append(yy, d1) d2 := Hoge{} d2.a = 5 d2.b = -8 yy = append(yy, d2) zz["d1"] = &yy[0] zz["d2"] = &yy[1] log.Println("yy[0] = ", yy[0], "*zz[d1] = ", *zz["d1"]) log.Println("yy[1] = ", yy[1], "*zz[d2] = ", *zz["d2"]) yy[0].a = -9 yy[0].b = 888 yy[1].a = -6 yy[1].b = 444 // これなら反映される log.Println("yy[0] = ", yy[0], "*zz[d1] = ", *zz["d1"]) log.Println("yy[1] = ", yy[1], "*zz[d2] = ", *zz["d2"]) }
という感じにすると
2017/03/31 13:04:14 yy[0] = {10 -20} *zz[d1] = {10 -20} 2017/03/31 13:04:14 yy[1] = {5 -8} *zz[d2] = {5 -8} 2017/03/31 13:04:14 yy[0] = {-9 888} *zz[d1] = {-9 888} # 反映されてる 2017/03/31 13:04:14 yy[1] = {-6 444} *zz[d2] = {-6 444}
ともあれ、コレを書いていて気づきましたが、[]Hogeで管理してるのがそもそもアレで、最初からmap[string]*Hogeで管理しとけば良かっただけですね、コレ。影響範囲が広いので今から全部直すのは現実的じゃないなぁ(それは全然別の話ですが・・・)