Label
在 break
和 continue
语句中是可选参数,而在 goto
语句中是必传的参数。Label
只在声明它的函数中有效。只要函数中声明了 Label
,那它在该函数的整个作用域都有效。
func main() {
fmt.Println(1)
goto End
fmt.Println(2)
End:
fmt.Println(3)
}
(注意!我们是在 goto 语句之后定义的 Label
)
> ./bin/sandbox
1
3
这里所指的作用域不包括嵌套函数的作用域:
func() {
fmt.Println(“Nested function”)
goto End
}()
End:
上面这段代码在编译时会报 label End not defined
错误。除此之外还会报:label End defined and not used
,因为我们需要保证只声明需要使用的 Label
。
Label
中没有块作用域的概念。所以不能在嵌套的块作用域中声明重复的 Label
:
goto X
X:
{
X:
}
编译上面的代码会报错提示 Label
已经存在了。
Label
的标识符和其他标识符具有不同的命名空间,所以不会与变量标识符等发生冲突。下面这段代码同时在 Label
和变量声明中都使用 x
作为标识符:
x := 1
goto x
x:
fmt.Println(x)
break 语句
break
语句一般都是用来跳出 for
或 switch
语句。在 Go 中也可以在 select
语句中使用 break
。
对于拥有类 C 语言编程经验的人肯定知道每个 case
语句都需要以 break
结尾。但是在大多数情况下程序都不希望执行到下一个 case
语句中。在 Go 中恰恰相反,如果需要执行下一个分句的代码可以使用 fallthrough
语句:
switch 1 {
case 1:
fmt.Println(1)
case 2:
fmt.Println(2)
}
> ./bin/sandbox
1
switch 1 {
case 1:
fmt.Println(1)
fallthrough
case 2:
fmt.Println(2)
}
> ./bin/sandbox
1
2
fallthrough 只能作为一个分句的最后一条语句使用。
break
语句不能跨越函数边界。
func f() {
break
}
func main() {
for i := 0; i < 10; i++ {
f()
}
}
上面的代码会报 break is not in a loop
错误。
一般情况下,break
可以用来跳出 for
,switch
或 select
语句。使用 Label
让 break
可以做更多的事情。
break
语句的 Label
必须对应围绕 break
的 for
,switch
或 select
语句。所以下面的代码不能通过编译:
FirstLoop:
for i := 0; i < 10; i++ {
}
for i := 0; i < 10; i++ {
break FirstLoop
}
它会报 invalid break label FirstLoop
。因为 Label
不在 break 对应的循环上。
break 可以跳出嵌套的循环:
OuterLoop:
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
fmt.Printf(“i=%v, j=%v\n”, i, j)
break OuterLoop
}
}
> ./bin/sandbox
i=0, j=0
如果 break
像下面这样用,那它不仅仅是退出 for
循环:
SwitchStatement:
switch 1 {
case 1:
fmt.Println(1)
for i := 0; i < 10; i++ {
break SwitchStatement
}
fmt.Println(2)
}
fmt.Println(3)
> ./bin/sandbox
1
3
break
可以在 for
,switch
或 select
语句中的任何地方退出并切换到指定 Label
。
continue 语句
他和 break
语句相似,只是会进入下一次迭代而不是退出循环(只能在循环中使用):
OuterLoop:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf(“i=%v, j=%v\n”, i, j)
continue OuterLoop
}
}
> ./bin/sandbox
i=0, j=0
i=1, j=0
i=2, j=0
goto 语句
goto
语句可以让程序切换到某个被 Label
标记的地方继续执行。
i := 0
Start:
fmt.Println(i)
if i > 2 {
goto End
} else {
i += 1
goto Start
}
End:
(注意:End
可以为空)
与 break
和 continue
语句不同,goto
语句必须指定 Label
。
goto
只能让程序移动到相同函数的某个位置。因此在执行 goto 的时候还有另外两条规则:
- 不能跳过变量声明,如果 goto 跳过,编译器会报
goto Done jumps over declaration of v at…
goto Done
v := 0
Done:
fmt.Println(v)
goto
不能切换到其他代码块,如果切换,编译器会报goto Block jumps into block starting at …
:
goto Block
{
Block:
v := 0
fmt.Println(v)
}
via: https://medium.com/golangspec/labels-in-go-4ffd81932339
作者:Michał Łowicki 译者:saberuster 校对:polaris1119
本文由 GCTT 原创翻译,Go语言中文网 首发。也想加入译者行列,为开源做一些自己的贡献么?欢迎加入 GCTT!
翻译工作和译文发表仅用于学习和交流目的,翻译工作遵照 CC-BY-NC-SA 协议规定,如果我们的工作有侵犯到您的权益,请及时联系我们。
欢迎遵照 CC-BY-NC-SA 协议规定 转载,敬请在正文中标注并保留原文/译文链接和作者/译者等信息。
文章仅代表作者的知识和看法,如有不同观点,请楼下排队吐槽
有疑问加站长微信联系(非本文作者))
