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所標誌的那條語句中。

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