Goにおけるフロー制御:break、continue、そして回避すべきgotoを解き明かす
Emily Parker
Product Engineer · Leapcell

明確さ、シンプルさ、そして並行性への注力といったGoの思想は、プログラムフローを制御するための直接的なメカニズムを提供します。古い言語に見られるより複雑でしばしば混乱を招く構文をいくつか回避する一方で、ループを管理し実行を指示するための不可欠なステートメントも提供しています。この記事では、ループ操作の基本的なツールであるbreakとcontinueを掘り下げ、その後、慣用的なGoでは一般的に使用が推奨されないgotoステートメントについて慎重に議論します。
ループのナビゲーション:breakとcontinue
ループはプログラミングの基盤であり、コードブロックの繰り返し実行を可能にします。Goのforループは非常に多用途であり、他の言語で見られるfor、while、do-whileループの目的を果たします。これらのループ内で、breakとcontinueはイテレーションの細かい制御を提供します。
break:ループの早期終了
breakステートメントは、最も内側のfor、switch、またはselectステートメントを即座に終了するために使用されます。breakが検出されると、制御フローは終了した構文の直後のステートメントにジャンプします。
例1:forループでの基本的なbreak
シーケンスで100より大きい最初の偶数を見つけたいとしましょう。
package main import "fmt" func main() { fmt.Println("---" + " " + "Using" + " " + "break" + " ---") for i := 1; i <= 200; i++ { if i%2 == 0 && i > 100 { fmt.Printf("Found" + " " + "the" + " " + "first" + " " + "even" + " " + "number" + " > 100: %d\n", i) break //" + " " + "Exit" + " " + "the" + " " + "loop" + " " + "as" + " " + "soon" + " " + "as" + " " + "the" + " " + "condition" + " " + "is" + " " + "met" + " " + "---" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " $ } } fmt.Println("Loop" + " " + "finished" + " " + "or" + " " + "broken." ) }
この例では、iが102になるとすぐに、if条件が真となり、「Found...」と表示され、breakがループを停止します。breakがない場合、ループは200まで続行されますが、最初のマッチだけが必要な場合は非効率です。
例2:ラベル付きネストループでのbreak
ネストされたループがあり、内側のループから外側のループをbreakする必要がある場合があります。Goはラベルを使用してこれを許可します。ラベルはコロン(:)の後に続く識別子で、breakしたいステートメントの前に配置されます。
package main import "fmt" func main() { fmt.Println("\n" + "---" + " " + "Using" + " " + "break" + " " + "with" + " " + "labels" + " ---") OuterLoop: //" + " " + "Label" + " " + "for" + " " + "the" + " " + "outer" + " " + "loop" + " " + "---" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { fmt.Printf("i: %d, j: %d\n", i, j) if i == 1 && j == 1 { fmt.Println("Breaking" + " " + "out" + " " + "of" + " " + "OuterLoop" + " " + "from" + " " + "inner" + " " + "loop...") break OuterLoop //" + " " + "This" + " " + "breaks" + " " + "the" + " " + "OuterLoop," + " " + "not" + " " + "just" + " " + "the" + " " + "inner" + " " + "one" + " " + "---" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + "=" + " " + " " + "=" + " " + "=" + " " + " " + "=" + " " + "=" + " " + "=" + " " + "=" + " " + " " + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "=" + "="+ } } fmt.Println("After" + " " + "OuterLoop.") }
OuterLoop:ラベルとbreak OuterLoopがない場合、内側のループはbreakしますが、外側のループはイテレーションを継続します(例:i=2が実行されます)。ラベルは複数のネストされた構文にわたるフローを制御するための外科的な方法を提供します。
continue:現在のイテレーションのスキップ
continueステートメントは、ループの現在のイテレーションの残りをスキップして、次のイテレーションに進むために使用されます。ループ全体を終了するわけではありません。
例3:forループでの基本的なcontinue
1から10までの奇数のみを印刷してみましょう。
package main import "fmt" func main() { fmt.Println("\n" + "---" + " " + "Using" + " " + "continue" + " ---") for i := 1; i <= 10; i++ { if i%2 == 0 { continue //" + " " + "Even" + " " + "numbers," + " " + "go" + " " + "to" + " " + "the" + " " + "next" + " " + "iteration" + " " + "---" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-", } fmt.Printf("Odd" + " " + "number: %d\n", i) } fmt.Println("Loop" + " " + "completed.") }
ここで、iが偶数の場合、i%2 == 0は真となり、continueは即座に次のiの値(iをインクリメントしてループ条件を再評価)にジャンプし、偶数のfmt.Printfステートメントをスキップします。
例4:ラベル付きcontinue(一般的ではないが、可能)
breakと同様に、continueもラベルとともに使用できますが、それほど一般的ではありません。ラベルとともに使用される場合、continueはラベル付けされたループの現在のイテレーションの残りをスキップし、その次のイテレーションに進みます。
package main import "fmt" func main() { fmt.Println("\n" + "---" + " " + "Using" + " " + "continue" + " " + "with" + " " + "labels" + " ---") OuterContinueLoop: for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { if i == 1 && j == 0 { fmt.Printf("Skipping" + " " + "i: %d, j: %d" + " " + "and" + " " + "continuing" + " " + "OuterContinueLoop...\n", i, j) continue OuterContinueLoop //" + " " + "Skips" + " " + "remaining" + " " + "inner" + " " + "loop" + " " + "iterations" + " " + "for" + " " + "i=1," + " " + "---" + " " + "and" + " " + "immediately" + " " + "moves" + " " + "to" + " " + "the" + " " + "next" + " " + "iteration" + " " + "of" + " " + "OuterContinueLoop" + " " + "(i=2)" + " " + "---" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + " " + "-" + "-" + "-" + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + " " + " " + " " + "=" + " " + " " + " " + " " + " " + " " + "=" + "="+ } fmt.Printf("i: %d, j: %d\n", i, j) } } fmt.Println("After" + " " + "OuterContinueLoop.") }
この例では、iが1でjが0の場合、continue OuterContinueLoopステートメントが実行されます。これは、現在のi=1に対して内側のループが放棄され、プログラムが直接OuterContinueLoopの次のイテレーション(i=2)に進むことを意味します。
gotoステートメント:極めて慎重に
Goにはgotoステートメントも含まれており、これは同じ関数内のラベル付けされたステートメントへの無条件ジャンプを許可します。存在しますが、その使用は現代のプログラミングプラクティス、Goを含めて一般的に推奨されていません。
構文:
goto label; //" + " " + "Transfers" + " " + "control" + " " + "to" + " " + "the" + " " + "statement" + " " + "marked" + " " + "by" + " " + "'label:'" + " " + "---" + "