go言語の配列の代入について調べてみました

goを書くとき配列の扱い方にちょっと気をつける必要がありそうだなと思ったので調べてみました。

配列全体の代入

goの場合配列を新しい変数に代入すると要素がコピーされます。

package main

import "fmt"

func main() {
  arr := [3]int{1, 2, 3}
  arr2 := arr
  arr2[1] = 10
  fmt.Println(arr)
  fmt.Println(arr2)
  fmt.Printf("arr: %T, arr2: %T\n", arr, arr2)
}

出力

[1 2 3]
[1 10 3]
arr: [3]int, arr2: [3]int

というようにarr2の要素を変更してもarrの要素は変更されていません。

一部の配列の代入

ただし、一部の配列を同じように変数に代入してみるとスライスとなりarrを指すようになります。

package main

import "fmt"

func main() {
  arr := [3]int{1, 2, 3}
  arr2 := arr[1:]
  arr2[1] = 10
  fmt.Println(arr)
  fmt.Println(arr2)
  fmt.Printf("arr: %T, arr2: %T\n", arr, arr2)
}

型推論を使用せずに代入するにはスライスの為

var arr2 []int = arr[0:2]

のようにします。

出力

[1 2 10]
[2 10]
arr: [3]int, arr2: []int

arr2では[]intとスライスになっていることがわかります。

配列からスライスを作る

範囲を指定するとスライスが作られるので、arr[:]のようにすべての範囲を指定すれば配列からスライスを作ることができます。 スライスなのでちゃんとappendできます。

package main

import "fmt"

func main() {
  arr := [3]int{1, 2, 3}
  arr2 := arr[:]
  arr2[1] = 10
  fmt.Println(arr)
  fmt.Println(arr2)
  fmt.Printf("arr: %T, arr2: %T\n", arr, arr2)
  fmt.Println(append(arr2, 4))
}

出力

[1 10 3]
[1 10 3]
arr: [3]int, arr2: []int
[1 10 3 4]