Go のコレクション

Go の配列、スライス、マップ

配列

配列は、コンパイル時に要素数が決まり、後から変更できない。型の前に [要素数] を付けて宣言する。インデックスは 0 から始まる。要素数は変更できないが、メモリー効率と性能に優れている。

package main

import "fmt"

func main() {
	a1 := [3]string{}
	a1[0] = "Red"
	a1[1] = "Green"
	a1[2] = "Blue"
	fmt.Println(a1[0], a1[1], a1[2])
}

実行結果:

Red Green Blue

配列の作成時に値を初期化できる。

a1 := [3]string{"Red", "Green", "Blue"}

初期値から要素数を決める場合は、数値の代わりに ... を記述できる。

a1 := [...]string{"Red", "Green", "Blue"}

スライス

スライスは要素数を変更できる。配列より少しオーバーヘッドがあるが、柔軟に扱える。

配列と異なり、要素数を指定せずに初期化するとスライスになる。

a1 := []string{"Red", "Green", "Blue"}

型の前に [] を付けて宣言する。要素の追加には append() を使用する。

package main

import "fmt"

func main() {
	a1 := []string{} // 初期要素を持たないスライス
	a1 = append(a1, "Red")
	a1 = append(a1, "Green")
	a1 = append(a1, "Blue")
	fmt.Println(a1[0], a1[1], a1[2])
}

実行結果:

Red Green Blue

len() は配列やスライスの長さ、cap() は容量を返す。長さは実際に使用している要素数であり、容量はメモリー上に確保している要素数である。容量を超えると、Go はより大きな領域を確保して既存のデータをコピーする。

package main

import "fmt"

func main() {
	a := []int{}
	for i := 0; i < 10; i++ {
		a = append(a, i)
		fmt.Println(len(a), cap(a))
	}
}

実行結果:

1 1
2 2
3 4
4 4
5 8
6 8
7 8
8 8
9 16
10 16

make(スライス型, 初期長, 初期容量) を使うと、スライスの領域を確保できる。初期容量を省略すると、初期長と同じ容量が確保される。あらかじめ容量を確保すると、再確保の回数を減らせる。

bufa := make([]byte, 0, 1024)

マップ

map[キー型]値型 を使うと、キーによって値を管理するマップを作成できる。

package main

import "fmt"

func main() {
	a1 := map[string]int{
		"x": 100,
		"y": 200,
	}

	fmt.Println(a1["x"])
	a1["z"] = 300
	delete(a1, "z")
	fmt.Println(len(a1))

	_, ok := a1["z"]
	if ok {
		fmt.Println("Exist")
	} else {
		fmt.Println("Not exist")
	}

	for key, value := range a1 {
		fmt.Printf("%s=%d\n", key, value)
	}
}

実行結果:

100
2
Not exist
x=100
y=200