雑学1473736 views
数学講師2891552 views
小学社会310694 views
中学社会669043 views
LaTeX962830 views
高校化学2926093 views
いろは3014035 views
中学数学624025 views
Computer368520 views
高校日本史190647 views
Help
Tools

English

Go のスライスのイテレーション(for range)

スライスの全要素を順番に処理するには、for range を使います。Go でスライスをループ処理する最も一般的な方法です。

基本的な for range

for range はスライスの各要素に対して、インデックスと値を返します。

fruits := []string{"apple", "banana", "cherry"}

for i, v := range fruits {
    fmt.Printf("%d: %s\n", i, v)
}
// 0: apple
// 1: banana
// 2: cherry

i にはインデックス、v には要素の値が代入されます。

インデックスのみ使う

値が不要な場合は、値の変数を省略できます。

fruits := []string{"apple", "banana", "cherry"}

for i := range fruits {
    fmt.Printf("Index: %d\n", i)
}

1つの変数だけで range を受けると、インデックスが代入されます。

値のみ使う

インデックスが不要な場合は、ブランク識別子 _ を使って無視します。

fruits := []string{"apple", "banana", "cherry"}

for _, v := range fruits {
    fmt.Println(v)
}
// apple
// banana
// cherry

Go では使わない変数を宣言するとコンパイルエラーになるため、_ で明示的に捨てる必要があります。

値はコピーされる

for range で取得する値は、元の要素のコピーです。ループ内で値を変更しても、元のスライスには影響しません。

numbers := []int{1, 2, 3}

for _, v := range numbers {
    v = v * 10 // コピーを変更しているだけ
}

fmt.Println(numbers) // [1 2 3](変更されない)

元のスライスを変更したい場合は、インデックスを使って直接アクセスします。

numbers := []int{1, 2, 3}

for i := range numbers {
    numbers[i] = numbers[i] * 10
}

fmt.Println(numbers) // [10 20 30]

通常の for ループとの比較

for range の代わりに、通常の for ループも使えます。

for range

簡潔で読みやすい。インデックスと値を同時に取得できる。

for i := 0; i < len(s); i++

インデックスを自由に制御できる。逆順や飛ばしループに向く。

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

// 逆順で処理
for i := len(numbers) - 1; i >= 0; i-- {
    fmt.Println(numbers[i])
}

// 1つ飛ばしで処理
for i := 0; i < len(numbers); i += 2 {
    fmt.Println(numbers[i])
}

特殊な順序で処理したい場合は、通常の for ループが適しています。

ループ中の要素追加に注意

for range の開始時にスライスの長さが決まるため、ループ中に要素を追加しても、追加した要素は処理されません。

numbers := []int{1, 2, 3}

for i, v := range numbers {
    if i == 0 {
        numbers = append(numbers, 4, 5)
    }
    fmt.Println(v)
}
// 1
// 2
// 3
// (4, 5 は出力されない)

ループ開始時の長さ(3)で繰り返しが決まるため、途中で追加した要素は処理対象になりません。ループ中にスライスを変更する場合は、この挙動を理解しておく必要があります。