menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right All_wiki chevron_right the-way-to-go_ZH_CN chevron_right eBook chevron_right 05.6.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    05.6.md
    3.05 KB / 2024-07-16 23:14:27
        # 5.6 标签与 goto
    
    `for`、`switch` 或 `select` 语句都可以配合标签 (label) 形式的标识符使用,即某一行第一个以冒号 (`:`) 结尾的单词(gofmt 会将后续代码自动移至下一行)。
    
    示例 5.13 [for6.go](examples/chapter_5/for6.go):
    
    (标签的名称是大小写敏感的,为了提升可读性,一般建议使用全部大写字母)
    
    ```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](examples/chapter_5/goto.go):
    
    ```go
    package main
    
    func main() {
    	i:=0
    	HERE:
    		print(i)
    		i++
    		if i==5 {
    			return
    		}
    		goto HERE
    }
    ```
    
    上面的代码会输出 `01234`。
    
    使用逆向的 `goto` 会很快导致意大利面条式的代码,所以不应当使用而选择更好的替代方案。
    
    **特别注意** 使用标签和 `goto` 语句是不被鼓励的:它们会很快导致非常糟糕的程序设计,而且总有更加可读的替代方案来实现相同的需求。
    
    一个建议使用 `goto` 语句的示例会在[第 15.1 章](15.1.md) 的 [simple_tcp_server.go](./examples/chapter_15/simple_tcp_server.go) 中出现:示例中在发生读取错误时,使用 goto 来跳出无限读取循环并关闭相应的客户端链接。
    
    定义但未使用标签会导致编译错误:`label … defined and not used`。
    
    如果您必须使用 `goto`,应当只使用正序的标签(标签位于 `goto` 语句之后),但注意标签和 `goto` 语句之间不能出现定义新变量的语句,否则会导致编译失败。
    
    示例 5.15 [goto2.go](examples/chapter_5/got2o.go):
    
    ```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.
    
    ```go
    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.
    
    ```go
    for i := 0; i<7 ; i++ {
    	if i%2 == 0 { continue }
    	fmt.Println("Odd:", i)
    }
    ```
    
    ## 链接
    
    - [目录](directory.md)
    - 上一节:[Break 与 continue](05.5.md)
    - 下一章:[函数](06.0.md)
    
    
    links
    file_download