Go言語豆知識(一)


豆知識

Go言語には、スライスという概念があります。スライスは値型ではなく、参照型のデータです。スライスは値型のArrayを参照しています。
スライスを拡張するにはappendメソッドを使います。もしスライスを拡張するときに、元に参照するArrayの長さを超えた場合は、新しい参照元Arrayを再作りすることになります。

コード

    slice1 := []int{1,2,3,4}
    slice2 := slice1[:3]

    fmt.Println("最初の段階、slice1,slice2はおなじ参照元Arrayを参照しています")
    fmt.Println(slice1)
    fmt.Println(slice2)

    fmt.Println(&slice1[0])
    fmt.Println(&slice2[0])
    fmt.Println()

    fmt.Println("slice2の長さはまた参照元Arrayの長さを超えていない")
    slice2 = append(slice2, 15)

    fmt.Println(slice1)
    fmt.Println(slice2)

    fmt.Println(&slice1[0])
    fmt.Println(&slice2[0])
    fmt.Println()

    fmt.Print("slice2は元のArrayの長さを超えました。")
    slice2 = append(slice2, 16)
    fmt.Println(slice1)
    fmt.Println(slice2)

    fmt.Println(&slice1[0])
    fmt.Println(&slice2[0])

最初の段階、slice1,slice2はおなじ参照元Arrayを参照しています
[1 2 3 4]
[1 2 3]
0xc0000b4000 <-参照元のアドレス(Array)
0xc0000b4000 <-参照元のアドレス(Array)

slice2の長さはまた参照元Arrayの長さを超えていない
[1 2 3 15]
[1 2 3 15]
0xc0000b4000 <-参照元のアドレス(Array)
0xc0000b4000 <-参照元のアドレス(Array)

slice2は元のArrayの長さを超えました。[1 2 3 15]
[1 2 3 15 16]
0xc0000b4000 <-参照元のアドレスA(Array)
0xc0000b8000 <-参照元のアドレス(新しいArray)

出力のように、最初slice1とslice2はおなじ参照元長さが4のArrayに参照しています。
slice1はArrayの0-3番目まで切り出しています。
slice2はArrayの0-2番目まで切り出しています。

1回目のappend作業をしてら、slice2の長さは3から4までに伸ばしました。そのときに参照元Arrayの長さは4です。slice2の拡張によって、参照元Arrayの4番目値が修正されました。

2回目のappend作業をしてら、slice2の長さは4から5までに伸ばしました。そのときに参照元Arrayの長さは4です。
もともとの参照元Array(長さ4)はslice2(長さ5)を納めないから、slice2の参照を収めるために、新しい参照元を作ることになります。
そのときに、slice1の参照元とslice2の参照元はそれぞれ異なる参照元になります。

0xc0000b4000 <-参照元のアドレスA(Array)
0xc0000b8000 <-参照元のアドレス(新しいArray)

説明