THINK

GolangにおけるSlice・mapの罠

12/1/2018

Golangはポインターがあるから、 ポインターが来たら 参照型 ! それ以外は !!

楽勝だぜヒャッハー!!! って思っていたら詰みましたorz

var m, n []int

m = make([]int, 3)
n = m

m[1] = 2

fmt.Println(m, n)

のとき、

[0 2 0] [0 2 0]

出力はこうなるよ…という話

どう見ても参照型ですね…

まじかーってなりましたw

引数に slice のポインタ渡す意味ないじゃん…

値 (複製) として渡すにはどうしたらいいんだー

解決策

func foo(m *[]int) {
    // ...
}

slice の参照渡しをしたい場合、上記は明らかに冗長なので、下記のようになります

func foo(m []int) {
    // ...
}

じゃあ、値渡しはどうしたら良いのかというと、 copy を使って複製したら良いらしい

ただし、複製するには上限が有って、複製先と複製元の長さが一致していないといけないらしい

どういうことかというと...

m := make([]int, 3)
n := make([]int, len(m))
copy(n, m)

こうなる…

で、多次元 slice はもう少し厄介...

2次元 slice を例にすると下記のようになる

m := [][]int {
    {1, 2, 3},
    {1, 2, 3},
    {1, 2, 3},
}
n := make([][]int, len(m))
for i := range m {
    n[i] := make([]int, len(m[i]))
    copy(n[i], m[i])
}

上記のようにしないと、複製出来ないらしい

以上

参考