【Go】配列とスライスの仕様について調べてみた

Goでスライスに出会ったので、とりあえず使えるレベルになるまで調べてみました。

下記を参考にしました。
blog.golang.org

配列(Array)

まず、配列について確認します。

書式

このように定義します。

  • [長さ]型

ここで、下記を実行してみます。出力結果は"0"です。

var arr [5]int
arr[0] = 0
fmt.Println(arr[0])

特徴

配列の初期化

上記の例に対して、値をいれていない要素も出力してみましょう。これも出力結果は"0"です。

fmt.Println(arr[1])

指定した配列型のゼロ値が格納されるため、配列は初期化しなくても使用可能です。

配列は値です。配列変数は配列全体を表します。そのため、配列変数をコピーするとすべての要素がコピーされることになります。スライスを使用すると、このような状態を回避し、効率的な処理にすることができます。

スライス(Slice)

スライス型はGoの配列型の上に構築された抽象概念です。(参考サイトの直訳)

スライスというのは、スライスが自体が要素を持つのではなく、スライスは配列とひも付いており、スライスの要素にアクセスするとひも付いた配列の要素が参照されます。スライスは配列とはことなり参照型です。

参考サイトの"Slice internals"の図を見ると非常にわかりやすいと思いますので、まずは参照してみてください。

書式

配列との違いは、長さを指定しない点です。

  • []型

下記を実行してみます。出力結果は[1 2 3 4 5]となります。これは、arr[:]がarr配列全体のスライスを作成することを意味しているからです。

// 配列の作成
arr := [5]int{1, 2, 3, 4, 5}
// 配列のスライス作成
var s []int
s = arr[:]
fmt.Println(s)

要素を指定するとその範囲だけのスライスを作成することができます。下記の実行結果は[2 3]になります。つまり、要素番号1から3未満が取り出されています。2つ目の要素番号は対象にならないので気をつけましょう。

s = arr[1:3]
fmt.Println(s)

表現方法は他にもありますが、スライスの基本的な書式は以上です。

特徴

スライスの初期化

例だと、配列の作成→スライスの作成となっていますがこれを同時に実行することができます。そのためには 組み込み関数のmakeを使用します。

- make(スライス型, 長さ, キャパシティ(省略可))

var s []byte
s = make([]byte, 5, 5)
// s == []byte{0, 0, 0, 0, 0}

それ以外にも、リテラスによる初期化ができます。

- スライス型 {要素の初期値, ....}

s := []int {1,2,3,4,5}

最後に

キャパシティの話とか値の追加とか、そういった話は記述しませんでしたが、とりあえずスライスを使うために理解するという目標の達成はできたかなと思います。もう少し操作の話はもしかしたら別でまとめるかも。