4
2

More than 1 year has passed since last update.

Go言語入門 学習メモ 3 繰り返し、ラベルの働き

Posted at

はじめに

船井総研デジタルのoswです。業務でGo言語を使うことになったのでこれから学習していきます。その備忘録です。参考になる方がいらっしゃれば幸いです。

対象読者

  • これからGo言語を学習する方
  • 既に他の言語で基本構文を学習されている方

学習環境

学習環境は次のようになっています。この環境の構築メモは下記記事にまとめてあります。ご興味がある方はご参照ください。

  • Windows 11 Home / 22H2
  • VSCode / 1.72.2
  • go version go1.19.2 windows/amd64
  • git version 2.38.0.windows.1

前回までの学習

前回は演算子、制御構文などを学習しました。

繰り返し

for文

Goには繰り返し構文として用意されているのはforしかないようです。書き方にバリエーションを付けることでwhileのように使い、無限ループにすることもできます。if同様、{}は必須です。()は付けるとコンパイルエラーになってしまうようです。

構文
// 条件が満たされている限り繰り返す
for 初期値; 繰り返し条件; 更新処理 {
    // 処理
}

// 省略形for文
for 繰り返し条件 {
    // 処理
}

// 無限ループ
for {
    // 処理
}
サンプルコード
package main

import "fmt"

func main() {

	fmt.Println("通常for文")
	for i := 0; i < 5; i++ {
		fmt.Println("i:", i)
	}

	fmt.Println("\n省略形for文")
	k := 0
	for k < 5 {
		fmt.Println("k:", k)
		k++
	}

	fmt.Println("\n無限ループ")
	j := 0
	for {
		fmt.Println("j:", j)
		if j == 4 {
			break
		}
		j++
	}

	// ()をつけるとコンパイルエラー
	// for (i := 0; i < 5; i++) {
		// fmt.Println("i:", i)
	// }
}
実行結果
通常for文
i: 0
i: 1
i: 2
i: 3
i: 4

省略形for文
k: 0
k: 1
k: 2
k: 3
k: 4

無限ループ
j: 0
j: 1
j: 2
j: 3
j: 4

break / continue / goto

これらは他の言語同様の働きをします。breakは現在のループ、switch文を抜けます。continueは現在のループ処理を中断し、次のループに移行します。gotoもあります。

サンプルコード
package main

import "fmt"

func main() {

	fmt.Println("breakの動作確認")
	for i := 0; i < 5; i++ {
		if i == 3 {
			break
		}
		fmt.Println("i:", i)
	}

	fmt.Println("\ncontinueの動作確認")
	for i := 0; i < 5; i++ {
		if i%2 == 0 {
			continue
		}
		fmt.Println("i:", i)
	}

	fmt.Println("\ngotoの動作確認")
	for i := 0; i < 5; i++ {
		if i == 3 {
			goto Goto
		}
		fmt.Println("i:", i)
	}

	return

Goto:
	fmt.Println("ジャンプ")
}
実行結果
breakの動作確認
i: 0
i: 1
i: 2

continueの動作確認
i: 1
i: 3

gotoの動作確認
i: 0
i: 1
i: 2
ジャンプ

ラベルの働き

Goではgoto以外にもラベル付けることができるようです。goto以外は実行した位置より外のスコープ、かつ上の行にラベルを記述します。指定した位置に飛ぶとgotoになってしまうのでそういう書き方になっているんでしょうか。

直感的に少々わかりづらいですが、ラベルはforに「紐づき」、breakなら紐づいたforを抜ける、continueなら紐づいたforから処理を再開、という動作になるようです。

構文
    // ラベル1は直後の、外側のforと紐づく
ラベル1:
    for {
        for {
            break ラベル1
        }
    }
    // 「紐づいたfor」を抜けるため、break後の制御はここに移る
    
    // ラベル2は直後の、外側のforと紐づく
ラベル2:
    for i := 0; i < 5; i++ {
        // 「紐づいたfor」に戻るため、continue後の制御はここに移る
        // 外側forのカウンタを更新し、処理を再開

        for {
            continue ラベル2
        }
    }
サンプルコード
package main

import "fmt"

func main() {

	const loopNum = 3

	fmt.Println("BreakLoop")
BreakLoop:
	// fmt.Println("ラベルとforの間にコードを書いてはいけない") コンパイルエラー
	for i := 0; i < loopNum; i++ {
		for j := 0; j < loopNum; j++ {
			if j == 1 {
				break BreakLoop
			}
			fmt.Println("i:", i, ", j:", j)
		}
	}
	
	fmt.Println("\nContinueLoop")
ContinueLoop:
	// fmt.Println("ラベルとforの間にコードを書いてはいけない") コンパイルエラー
	for i := 0; i < loopNum; i++ {
		for j := 0; j < loopNum; j++ {
			if j == 1 {
				continue ContinueLoop
			}
			fmt.Println("i:", i, ", j:", j)
		}
	}
}
実行結果
BreakLoop
i: 0 , j: 0

ContinueLoop
i: 0 , j: 0
i: 1 , j: 0
i: 2 , j: 0

おわりに

今回はここまでです。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2