【Golang】配列とスライスの違いについて


配列と参照型のスライスの勉強したのですが自分なりにまとめてみました。
まだ書籍で勉強し始めた程度なので思いつけば随時更新していければと思っています。

環境

  • golang v1.11.4

配列とスライスの違い

配列

  • 格納する要素数を増やすことができない
  • 値を指定しない場合
    • int型=0
    • string型=""
    • bool型=false

スライス

  • 参照型
  • 値を指定しない場合 nil
  • スライスを扱う際注意すること
    • 要素数
    • 容量
    • 要素の各値

容量は必要に応じて自動的にスケールするが、パフォーマンスを考えてハンドリングすべき

配列の生成

// 要素指定なし、容量3
array := [3]int

// [0 0 0]
// 要素指定、容量3
array := [3]int{1, 3, 5}

// [1 3 5]

スライスの生成

// int型、要素数10、容量10を指定
slice1 := make([]int, 10) // -> [0 0 0 0 0 0 0 0 0 0]

// int型、要素数10、容量5を指定
slice2 := make([]int, 10, 5) // ->[0 0 0 0 0]

要素の各値を指定する場合は配列の生成と激似

// [1, 3, 5]の要素を収納。要素数3、容量3
slice3 := []int{1,3,5}

下記にのように変数を書き換える時は配列型と参照型が全く別の挙動を取るので注意。

package main

import "fmt"

// 配列を2乗する関数
func arraySquare(numbers [3]int) {
    for i, v := range numbers {
        numbers[i] = v * v
    }
    return
}

// スライスを2乗する関数
func sliceSquare(numbers []int) {
    for i, v := range numbers {
        numbers[i] = v * v
    }
    return
}

func main() {
    // 配列で宣言をし、関数で2乗、もとのarrayAを出力
    arrayA := [3]int{1, 2, 3}
    arraySquare(arrayA)
    fmt.Println(arrayA)  // [ 1 2 3]

    // スライスを宣言し、関数で2乗、もとのsliceAを出力
    sliceA := []int{1, 2, 3}
    sliceSquare(sliceA)
    fmt.Println(sliceA)  // [1 4 9]
}