golang中如何理解break与goto标签执行顺序

平时我们经常会用 for 和 select 语句来搭配使用来实现不断的通讯。
比如一个 goroutine 不断的从管道中发送字符,另一个不断的接收字符,当在管道关闭后,正常结束程序的执行。
如果我们不使用类似break, goto 等配合跳出到指定的标签,那么程序就不好控制正常结束了。
这里简要说明break,goto配合标签使用时的执行逻辑如下:
break是跳出到标签对应的当前指令,然后执行其下一条指令。
goto是跳往将要执行的指令。

goto + 标签

package main

import (
	"fmt"
	"time"
)

func main() {
	intChan := make(chan int)
	go func() {
		for i := 0; i < 5; i++ {
			time.Sleep(time.Second)
			intChan <- i
		}
		defer close(intChan)
	}()
	for {
		select {
		case i, ok := <-intChan:
			if !ok {
				fmt.Println("in break")
				goto LOOP
			}
			fmt.Println(i)
		case <-time.After(500 * time.Millisecond):
			fmt.Println("time expired")
		}
	}
LOOP:
	fmt.Println("end")
}

break + 标签

对于上述代码,如果我们想要使用break来改写,则如下

package main

import (
	"fmt"
	"time"
)

func main() {
	intChan := make(chan int)
	go func() {
		for i := 0; i < 5; i++ {
			time.Sleep(time.Second)
			intChan <- i
		}
		defer close(intChan)
	}()

	for {
		select {
		case i, ok := <-intChan:
			if !ok {
				fmt.Println("in break")
				break LOOP
			}
			fmt.Println(i)
		case <-time.After(500 * time.Millisecond):
			fmt.Println("time expired")
		}
	}
LOOP:
	fmt.Println("end")
}

但这样是不会通过编译的,显示如下:

# command-line-arguments
./breakloop.go:23:11: break label not defined: LOOP
./breakloop.go:30:1: label LOOP defined and not used

为什么呢?因为break这个不是goto,几乎可以到达程序的任何一个地方。它只能在其定义了后,才可以使用。

现在将其位置调整成如下,即可正常工作。

package main

import (
	"fmt"
	"time"
)

func main() {
	intChan := make(chan int)
	go func() {
		for i := 0; i < 5; i++ {
			time.Sleep(time.Second)
			intChan <- i
		}
		defer close(intChan)
	}()
LOOP:
	for {
		select {
		case i, ok := <-intChan:
			if !ok {
				fmt.Println("in break")
				break LOOP
			}
			fmt.Println(i)
		case <-time.After(500 * time.Millisecond):
			fmt.Println("time expired")
		}
	}
	fmt.Println("end")
}

上面的LOOP标签,就指代了当前的for{}语句,当用break LOOP时,其会跳过当前语句(for{}),而开始执行下一条语句(也即 fmt.Println("end"))
如此,则满足我们需求了。如果break时不带标签,那么其只退出当前的 select语句,无法跳出 for,就永远不会结束了。
总之,break LOOP,需要出现在LOOP所标志的那条语句中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章