這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。`Label` 在 `break` 和 `continue` 語句中是選擇性參數,而在 `goto` 語句中是必傳的參數。`Label` 只在聲明它的函數中有效。只要函數中聲明了 `Label` ,那它在該函數的整個範圍都有效。```gofunc main() {fmt.Println(1)goto Endfmt.Println(2)End:fmt.Println(3)}```(注意!我們是在 goto 語句之後定義的 `Label`)```shell> ./bin/sandbox13```這裡所指的範圍不包括嵌套函數的範圍:```gofunc() {fmt.Println(“Nested function”)goto End}()End:```上面這段代碼在編譯時間會報 `label End not defined` 錯誤。除此之外還會報:`label End defined and not used`,因為我們需要保證只聲明需要使用的 `Label`。`Label` 中沒有塊範圍的概念。所以不能在嵌套的塊範圍中聲明重複的 `Label`:```gogoto XX:{X:}```編譯上面的代碼會報錯提示 `Label` 已經存在了。`Label` 的標識符和其他標識符具有不同的命名空間,所以不會與變數標識符等發生衝突。下面這段代碼同時在 `Label` 和變數聲明中都使用 `x` 作為標識符:```gox := 1goto xx: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/sandbox1switch 1 {case 1:fmt.Println(1)fallthroughcase 2:fmt.Println(2)}> ./bin/sandbox12```> fallthrough 只能作為一個分句的最後一條語句使用。`break` 語句不能跨越函數邊界。```gofunc 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` 語句。所以下面的代碼不能通過編譯:```goFirstLoop:for i := 0; i < 10; i++ {}for i := 0; i < 10; i++ {break FirstLoop}```它會報 `invalid break label FirstLoop` 。因為 `Label` 不在 break 對應的迴圈上。break 可以跳出嵌套的迴圈:```goOuterLoop:for i := 0; i < 10; i++ {for j := 0; j < 10; j++ {fmt.Printf(“i=%v, j=%v\n”, i, j)break OuterLoop}}``````> ./bin/sandboxi=0, j=0```如果 `break` 像下面這樣用,那它不僅僅是退出 `for` 迴圈:```goSwitchStatement:switch 1 {case 1:fmt.Println(1)for i := 0; i < 10; i++ {break SwitchStatement}fmt.Println(2)}fmt.Println(3)``````> ./bin/sandbox13````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/sandboxi=0, j=0i=1, j=0i=2, j=0```## goto 語句`goto` 語句可以讓程式切換到某個被 `Label` 標記的地方繼續執行。```i := 0Start:fmt.Println(i)if i > 2 {goto End} else {i += 1goto Start}End:```(注意:`End` 可以為空白)與 `break` 和 `continue` 語句不同,`goto` 語句必須指定 `Label`。`goto` 只能讓程式移動到相同函數的某個位置。因此在執行 goto 的時候還有另外兩條規則:- 不能跳過變數聲明,如果 goto 跳過,編譯器會報 `goto Done jumps over declaration of v at…````gogoto Donev := 0Done:fmt.Println(v)```- `goto` 不能切換到其他代碼塊,如果切換,編譯器會報 `goto Block jumps into block starting at …`:```gogoto Block{Block:v := 0fmt.Println(v)}```
via: https://medium.com/golangspec/labels-in-go-4ffd81932339
作者:Michał Łowicki 譯者:saberuster 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
537 次點擊