ラベル付きbreak, continue, goto
Goのプログラムを見ていて、何年ぶりか分からないくらい久しぶりにラベル付きbreakを見かけた。
ラベル付きステートメント
この通り、break, continueの他に、gotoにも使えるらしい。(つまりgoto文をGoは許している)
試してみた
ラベルは自分がいるスコープの外に定義されているものしか参照できない模様。
試しに以下のサンプルコードを書いて動かしてみた。
package main import ( "fmt" "time" ) func main() { L: for i := 1; true; i++ { for j := 1; true; j++ { fmt.Printf("i=%v> j=%v\n", i, j) if i == 2 && j == 2 { continue L } if i%2 != 0 && j == 3 { goto L2 } if j == 3 { break L } time.Sleep(200 * time.Millisecond) } L2: } }
自分でも挙動が読めない中、試行錯誤した結果、上記プログラムを動かすと以下の出力が得られる。
出力内容
i=1> j=1 i=1> j=2 i=1> j=3 // ここで goto L2 の条件にマッチしてjのループを抜ける i=2> j=1 i=2> j=2 // ここで continue L の条件にマッチしてjのループを抜ける i=3> j=1 i=3> j=2 i=3> j=3 i=4> j=1 i=4> j=2 i=4> j=3 // ここで break L の条件にマッチしてiのループを抜ける
当然これはやっておくでしょう
goto出てきたら当然コレはやっとくでしょう。
package main import ( "fmt" "strings" "time" ) var ora = []string{ "ハァ テレビもねぇ! ラジオもねぇ!", "クルマもそれほど走ってねぇ!", "ピアノもねぇ! バーもねぇ! おまわり毎日ぐーるぐる!", } const delay = time.Duration(750 * time.Millisecond) func Sing(message string) { xs := strings.Split(message, " ") length := len(xs) for i, x := range xs { fmt.Print(x) if i+1 < length { fmt.Print(" ") time.Sleep(delay) } } time.Sleep(delay) fmt.Println() } func main() { for i := 0; true; i++ { Sing(ora[i]) if i >= 2 { Sing("おらこんな村いやだぁ〜 おらこんな村いやだぁ〜") Sing("東京へ出るだぁ〜〜〜") goto Tokyo } } Tokyo: for i := 0; true; i++ { Sing("東京へ出だな〜ら 銭コア貯めでぇ 東京でベコ飼うだぇ〜〜") break Tokyo } }
最終的にここまで調整しました。