在Golang中能使用Label
的有goto
, break
, continue
.,這篇文章就介紹下Golang中Label
使用和注意點.
注意點:
Label
在continue, break中是可選的
, 但是在goto
中是必須的
- 作用范圍: 定義
Label
的函數體內. Label
可以聲明在函數體的任何位置, 不管Label
聲明在調用點
的前面還是后面.
一. goto
下面就以goto
為例子展示上面三點特點.
1.Label
在goto
是必須的
package main import ( "fmt" ) func main() { fmt.Println(1) goto End //goto 10: syntax error: unexpected . at end of statement fmt.Println(2) End: fmt.Println(3) }
輸出
Output: 1 3
2.Label
可以聲明在函數體的任何地方
package main import ( "fmt" ) func main() { End: fmt.Println(1) goto End fmt.Println(2) fmt.Println(3) }
輸出
Output 1 1 1 ....
3.Label
的作用范圍是在函數體中
package main import ( "fmt" ) func main() { fmt.Println(1) goto End fmt.Println(2) } End: fmt.Println(3)
輸出
Output: syntax error: non-declaration statement outside function body
4.Label
在嵌套函數(閉包)是不可用的. 不管是在閉包里
調用閉包外
的Label, 還是在閉包外
調用閉包里
的Label
package main import ( "fmt" ) func main() { fmt.Println(1) func() { fmt.Println("Nested function") goto End }() End: fmt.Println(2) }
輸出
Output 11:label End not defined 13:label End defined and not used
5.不能重復定義Label
package main import ( "fmt" ) func main() { fmt.Println(1) goto End End fmt.Println(2) { End: fmt.Println(3) } }
輸出
Output 14: label End already defined at ./label.go:11
6.Label
和變量名是不沖突的
, 可以定義一個名為x
的變量和名為x
的Label(不過不建議這么用, 這么寫會被人罵的); 而且Label
是區分大小寫的.
package main import ( "fmt" ) func main() { x := 1 fmt.Println(x) goto x x: fmt.Println(2) }
輸出
Output: 1 2
7.變量的聲明必須在goto
之前.
package main import ( "fmt" ) func main() { goto End j := 2 fmt.Println(j) End: fmt.Println(1) }
輸出
Output goto End jumps over declaration of i at ./label.go:9
這是為什么呢? 因為任何變量的聲明都不能被跳過.
需要改成下面的形式
package main import ( "fmt" ) func main() { j := 2 goto End fmt.Println(j) End: fmt.Println(2) }
二. break(不帶label)
break
一般用來跳出最近
一層的switch
和for
, 注意不能用在select
上
1.單層循環
package main import ( "fmt" ) func main() { for i := 0; i < 10; i++ { fmt.Println(i) if i == 3 { break } } }
輸出
Output 0 1 2 3
2.雙層循環
package main import ( "fmt" ) func main() { for i := 0; i < 3; i++ { for j := 0; j < 5; j++ { fmt.Println("i:", i, ",j:", j) if j == 2 { break } } } }
輸出
Output i: 0 ,j: 0 i: 0 ,j: 1 i: 0 ,j: 2 i: 1 ,j: 0 i: 1 ,j: 1 i: 1 ,j: 2 i: 2 ,j: 0 i: 2 ,j: 1 i: 2 ,j: 2
從這個例子可以看出break
只能跳出最近for
3.對於c/c++
來說, switch/case
一般都是配合break
來使用的.但是在golang
中switch/case
不需要break
就能夠實現和c/c++
一樣的效果.
package main import ( "fmt" ) func main() { i := 1 switch { case i == 0: fmt.Println(i) case i == 1: fmt.Println(i) //break 這里可以使用`break`,但是么有啥效果, 不如不寫 case i == 2: fmt.Println(i) } }
輸出
Output 1
如果想繼續往下執行, 需要使用fallthrough
package main import ( "fmt" ) func main() { i := 1 switch { case i == 0: fmt.Println(0) case i == 1: fmt.Println(1) fallthrough case i == 2: fmt.Println(2) } }
輸出
Output: 1 2
4.break
在函數里是不起作用的, 不能傳遞出來.
package main func f() { break } func main() { for i := 0; i < 10; i++ { f() } }
輸出
output 4: break is not in a loop
三.break(Label)
break
攜帶label
可以用在for
,switch
,select
上.
1.對於for
/select
/switch
,Label
必須緊挨着他們.
FirstLoop: for i := 0; i < 10; i++ { //invalid break label FirstLoop } for i := 0; i < 10; i++ { break FirstLoop }
必須改成這樣
func main() { for i := 0; i < 10; i++ { fmt.Println(i) } FirstLoop: for i := 0; i < 10; i++ { break FirstLoop } }
對於select
和switch
也是一樣.
func main() { FirstLoop: j := 1 switch j { case 0: fmt.Println(0) case 1: fmt.Println(1) break FirstLoop // invalid break label FirstLoop } }
2.一般來說break
只能跳出最近一層的for
, switch
, 但是break Label
就可以直接跳出最外面的循環.
func main() { OuterLoop: for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { fmt.Printf("i=%v, j=%v\n", i, j) break OuterLoop } } }
Output
i=0, j=0
輸出
SwitchStatement: switch 1 { case 1: fmt.Println(1) for i := 0; i < 10; i++ { break SwitchStatement } fmt.Println(2) } fmt.Println(3)
輸出
Output 1 3
四. continue
continue
用法基本上和break
差不多.1.正常的用法, 調過當前循環, 繼續執行下一次
package main import ( "fmt" ) func main() { for i := 0; i < 5; i++ { if i == 3 { continue } fmt.Println(i) } }
輸出
Output 0 1 2 4
2.continue
和label
一起使用(其實和不使用Label效果一樣)
func main() { Test: for i := 0; i < 5; i++ { if i == 3 { continue Test } fmt.Println(i) } }
輸出
Output 0 1 2 4
3.continue
和雙層循環一起使用
OuterLoop: for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { fmt.Printf(“i=%v, j=%v\n”, i, j) continue OuterLoop } }
輸出
Output i=0, j=0 i=1, j=0 i=2, j=0