5.6 标签与 goto

最后更新于:2022-04-01 20:54:39

for、switch 或 select 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号(`:`)结尾的单词(gofmt 会将后续代码自动移至下一行)。 示例 5.13 [for6.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_5/for6.go): (标签的名称是大小写敏感的,为了提升可读性,一般建议使用全部大写字母) ~~~ package main import "fmt" func main() { LABEL1: for i := 0; i <= 5; i++ { for j := 0; j <= 5; j++ { if j == 4 { continue LABEL1 } fmt.Printf("i is: %d, and j is: %d\n", i, j) } } } ~~~ 本例中,continue 语句指向 LABEL1,当执行到该语句的时候,就会跳转到 LABEL1 标签的位置。 您可以看到当 j==4 和 j==5 的时候,没有任何输出:标签的作用对象为外部循环,因此 i 会直接变成下一个循环的值,而此时 j 的值就被重设为 0,即它的初始值。如果将 continue 改为 break,则不会只退出内层循环,而是直接退出外层循环了。另外,还可以使用 goto 语句和标签配合使用来模拟循环。 示例 5.14 [goto.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_5/goto.go): ~~~ package main func main() { i:=0 HERE: print(i) i++ if i==5 { return } goto HERE } ~~~ 上面的代码会输出 `01234`。 使用逆向的 goto 会很快导致意大利面条式的代码,所以不应当使用而选择更好的替代方案。 **特别注意** 使用标签和 goto 语句是不被鼓励的:它们会很快导致非常糟糕的程序设计,而且总有更加可读的替代方案来实现相同的需求。 一个建议使用 goto 语句的示例会在第 15.1 章的 simple_tcp_server.go 中出现:示例中在发生读取错误时,使用 goto 来跳出无限读取循环并关闭相应的客户端链接。 定义但未使用标签会导致编译错误:`label … defined and not used`。 如果您必须使用 goto,应当只使用正序的标签(标签位于 goto 语句之后),但注意标签和 goto 语句之间不能出现定义新变量的语句,否则会导致编译失败。 示例 5.15 [goto2.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_5/got2o.go): ~~~ // compile error goto2.go:8: goto TARGET jumps over declaration of b at goto2.go:8 package main import "fmt" func main() { a := 1 goto TARGET // compile error b := 9 TARGET: b += a fmt.Printf("a is %v *** b is %v", a, b) } ~~~ **问题 5.3** 请描述下面 for 循环的输出: 1. ~~~ i := 0 for { //since there are no checks, this is an infinite loop if i >= 3 { break } //break out of this for loop when this condition is met fmt.Println("Value of i is:", i) i++; } fmt.Println("A statement just after for loop.") ~~~ 2. ~~~ for i := 0; i<7 ; i++ { if i%2 == 0 { continue } fmt.Println("Odd:", i) } ~~~
';