👨‍👨‍👧

配列 ( Go入門連載 第5回 )

2021/03/06に公開

シリーズの目次

  1. Goの導入 for MacOS
  2. パッケージ
  3. 変数とデータ型
  4. 条件分岐
  5. ループ処理
  6. 配列
  7. 関数

配列

コンパイル時に個数が決まっていて変更不可のものを 配列 と言います。型名の前に [個数] をつけて宣言します。配列のインデックスは 0 からはじまります。途中で個数を変更することはできませんが、メモリ効率や性能の点で優れています。

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

当然、初期化時にこのような形で値を渡すことも可能です。

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

この場合、初期化によって個数が決まるので、個数を ... と書くことによって省略可能です。

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

また、Go言語では以下のように書くことで配列の添字と値でループすることが可能です。
下の例では i は 0 → 1 → 2 というように変化し、 n は 1 → 10 → 100 というように変化していきます。

arr := [...]int{1, 10, 100}
for i, n := range arr {
    fmt.Println(i, n)
}

スライス

メモリ効率や速度は若干落ちますが、個数を変更可能なものを スライス と呼びます。型名の前に [] をつけて宣言します。スライスには append() を用いて要素を追加することができます。

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

len() は配列やスライスの長さ(length)、cap() は容量(capacity)を求めます。長さは実際に使用されている数、容量はメモリ上に確保されている数です。容量を超えると、倍の容量のメモリが新たに確保され、既存データがコピーされます

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

また、以下のようにすることで配列の一部分を取得することが可能です。

A := [...]int{0, 1, 2, 3}
B := A[1:3] // => 1 2   (2文字目から3文字目までを取得)
C := A[1:]  // => 1 2 3 (2文字目から最後までを取得)
D := A[:3]  // => 0 1 2 (最初から3文字目までを取得)

スライスの場合、make(スライス型, 初期個数, 初期容量) を用いたメモリの確保ができます。初期容量を省略した場合は初期個数と同じ容量が確保されます。容量をあらかじめ確保しておくことで、容量超過時の再確保を減らして速度を速めることができます。

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

マップ(map)

map[キーの型]値の型 を用いて連想配列のようなマップを使用することができます。

// マップを定義する
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)
}

Discussion