Go言語のfor文の基本的な使い方について解説
この記事では、Go言語のfor
ループに焦点をあて、シンプルで柔軟な繰り返し処理の使い方について解説します。
基本的な構文と実例を通して、直感的に理解しやすいループ処理のパターンを紹介します。
基本的なfor文の構文
初期化・条件・後処理の記述方法
Goのfor文は、初期化、条件、後処理の3つの要素をセミコロンで区切って記述する形式が一般的です。
例えば、変数を初期化して、条件が真である間ループし、後処理として変数を更新する場合は、以下のように書きます。
package main
import "fmt"
func main() {
// 変数iを0で初期化し、iが5未満の場合にループ、
// ループ終了後にiをインクリメントする
for i := 0; i < 5; i++ {
fmt.Println("カウンタ:", i) // カウンタの値を表示
}
}
カウンタ: 0
カウンタ: 1
カウンタ: 2
カウンタ: 3
カウンタ: 4
この形式は、数式
シンプルなループ処理の書き方
for文は、シンプルなループ処理のためにも利用できます。
ループ変数や後処理が不要な場合でも、1行でループの条件を書くことが可能です。
例えば、単純に条件に合致する間だけループさせるケースを示します。
package main
import "fmt"
func main() {
counter := 0
// 条件のみを記述したfor文でカウンタが3未満の間ループ
for counter < 3 {
fmt.Println("シンプルループ:", counter)
counter++ // カウンタを明示的に更新
}
}
シンプルループ: 0
シンプルループ: 1
シンプルループ: 2
このように、初期化や後処理を外部で行い、条件だけをfor文に記述することで柔軟なループが実現できます。
多様なfor文の利用方法
条件式のみを用いるループ(while文風)
Goではwhile文が存在しないため、条件式のみを使ったfor文で同様の処理を実現します。
条件が真である限りループを継続するため、以下の例のように使用します。
package main
import "fmt"
func main() {
// counterの初期化
counter := 0
// 条件のみのfor文はwhile文と同じ動作をします
for counter < 4 {
fmt.Println("条件式のみループ:", counter)
counter++ // カウンタを更新して条件に影響させる
}
}
条件式のみループ: 0
条件式のみループ: 1
条件式のみループ: 2
条件式のみループ: 3
条件を満たさなくなればループは終了するため、while文と同様に扱えます。
無限ループの実現(for{}の活用法)
初期化や条件、後処理を一切記述しないfor文は無限ループを実現するために使用します。
必要なタイミングでbreak文を用いてループを抜けることで、柔軟にループ処理を構成できます。
package main
import "fmt"
func main() {
counter := 0
// 無限ループの開始
for {
// 必要な処理を実行
fmt.Println("無限ループ:", counter)
counter++
// counterが5になったらループを終了する
if counter >= 5 {
break // ループ終了
}
}
}
無限ループ: 0
無限ループ: 1
無限ループ: 2
無限ループ: 3
無限ループ: 4
必要なときにbreak文を使用することで、無限ループの中で適切に処理を抜けられます。
実践的な反復処理例
スライス・配列の反復処理
Goでは、スライスや配列の各要素に対してfor文を使って反復処理が可能です。
代表的な方法はrange
キーワードを使う方法で、インデックスと値を簡単に取得できます。
package main
import "fmt"
func main() {
// 数値を格納するスライスを定義
numbers := []int{10, 20, 30, 40, 50}
// スライスの各要素を反復処理
for index, value := range numbers {
fmt.Printf("インデックス: %d, 値: %d\n", index, value)
}
}
インデックス: 0, 値: 10
インデックス: 1, 値: 20
インデックス: 2, 値: 30
インデックス: 3, 値: 40
インデックス: 4, 値: 50
この方法は配列にも同様に適用でき、可読性の高いコードが作成可能です。
Mapでのキーと値の取得
range
キーワードは、Map型の反復処理にも利用できます。
Mapの各要素に対してキーと値を取得する例を示します。
package main
import "fmt"
func main() {
// 文字列をキー、整数を値としたMapを定義
scoreMap := map[string]int{
"alice": 85,
"bob": 90,
"carol": 78,
}
// Mapのキーと値を反復処理
for key, value := range scoreMap {
fmt.Printf("名前: %s, スコア: %d\n", key, value)
}
}
名前: alice, スコア: 85
名前: bob, スコア: 90
名前: carol, スコア: 78
Mapの場合、要素の順序は保証されない点に注意してください。
rangeキーワードによる反復
range
キーワードは、スライス、配列、Mapだけでなく、文字列やチャネルに対しても使用できます。
ここでは、文字列中の各文字(ルーン)を反復処理する例を示します。
package main
import "fmt"
func main() {
message := "こんにちは"
// 文字列中の各ルーンを反復処理
for index, char := range message {
fmt.Printf("位置: %d, 文字: %c\n", index, char)
}
}
位置: 0, 文字: こ
位置: 3, 文字: ん
位置: 6, 文字: に
位置: 9, 文字: ち
位置: 12, 文字: は
文字列のルーンごとの反復処理により、UTF-8対応の柔軟な実装が可能です。
ループ制御と注意点
breakとcontinueの使い分け
ループ中の特定の条件で処理を中断したり、次の反復処理に移る場合に、break
やcontinue
を使用できます。
以下の例では、条件に合致する場合にcontinue
でスキップし、別の条件でbreak
を用いてループを終了しています。
package main
import "fmt"
func main() {
// 0から9までループ
for i := 0; i < 10; i++ {
// もしiが偶数の場合は、スキップする
if i%2 == 0 {
continue
}
// iが7になったらループを終了する
if i == 7 {
break
}
fmt.Println("ループ制御:", i)
}
}
ループ制御: 1
ループ制御: 3
ループ制御: 5
このように、continue
は現在の反復を終了して次に進み、break
はループ全体を終了します。
ネストされたループでの適用
ネストされたループの場合、break
やcontinue
は内側のループに対して作用します。
外側のループも同時に終了させたい場合、ラベルを付けて指定する方法があります。
package main
import "fmt"
func main() {
// 外側のループにラベルを付ける
OuterLoop:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
// 特定の条件で外側のループも終了する
if i*j > 4 {
break OuterLoop // 外側のループ全体を抜ける
}
fmt.Printf("i: %d, j: %d\n", i, j)
}
}
}
i: 1, j: 1
i: 1, j: 2
i: 1, j: 3
i: 2, j: 1
ラベルを用いると、対象のループを明確に指定でき、意図しないループ継続を防ぐことができます。
ループ変数のスコープと再代入時の留意点
ループ変数はfor文のブロック内で有効です。
そのため、ループ外で同名の変数を使用しても問題ありません。
また、ループ変数が予期せず上書きされないように、変数のスコープに注意する必要があります。
使い方の例として、for文内でループ変数をそのまま別のゴルーチンに渡す際の注意点を示します。
package main
import (
"fmt"
"time"
)
func main() {
// クロージャでループ変数を捕捉する際に意図した値として使うためには、
// 変数をローカルコピーすると安全です
for i := 0; i < 3; i++ {
// 変数コピーを行う
value := i
go func() {
// valueを使って出力
time.Sleep(10 * time.Millisecond)
fmt.Println("ゴルーチン内の値:", value)
}()
}
// 十分な待ち時間を設ける
time.Sleep(50 * time.Millisecond)
}
ゴルーチン内の値: 0
ゴルーチン内の値: 1
ゴルーチン内の値: 2
ループ変数の再代入やクロージャへの渡し方に注意することで、意図しない動作を防ぐことができます。
まとめ
この記事では、Go言語のfor文の基本的な構文と応用例、ならびにループ制御の注意点について詳しく解説しました。
各サンプルコードと具体例によって、for文の使い方が明確に理解できる内容となっています。
ぜひ実際にコードを動かしながら、学習を進めてみてください。