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]