Golang中Label的用法


在Golang中能使用Label的有gotobreakcontinue.,這篇文章就介紹下Golang中Label使用和注意點.

注意點:

  1. Label在continue, break中是可選的, 但是在goto中是必須的
  2. 作用范圍: 定義Label的函數體內.
  3. Label可以聲明在函數體的任何位置, 不管Label聲明在調用點的前面還是后面.

一. goto

下面就以goto為例子展示上面三點特點.

1.Labelgoto是必須的

package main

import (
    "fmt"
)

func main() {
    fmt.Println(1)
    goto End
    //goto  10: syntax error: unexpected . at end of statement
    fmt.Println(2)
End:
    fmt.Println(3)
}

輸出

Output:
1
3

2.Label可以聲明在函數體的任何地方

package main

import (
    "fmt"
)

func main() {
End:
    fmt.Println(1)
    goto End
    fmt.Println(2)
    fmt.Println(3)
}

輸出

Output
1
1
1
....

3.Label的作用范圍是在函數體中

package main

import (
    "fmt"
)

func main() {
    fmt.Println(1)
    goto End
    fmt.Println(2)
}

End:
    fmt.Println(3)

 輸出

Output:
syntax error: non-declaration statement outside function body

4.Label在嵌套函數(閉包)是不可用的. 不管是在閉包里調用閉包外的Label, 還是在閉包外調用閉包里的Label

package main

import (
    "fmt"
)

func main() {
    fmt.Println(1)
    func() {
        fmt.Println("Nested function")
        goto End
    }()
End:
    fmt.Println(2)
}

 輸出

Output
11:label End not defined
13:label End defined and not used

5.不能重復定義Label

package main

import (
    "fmt"
)

func main() {
    fmt.Println(1)
    goto End
    
End
    fmt.Println(2)
    {
    End:
        fmt.Println(3)
    }
}

 輸出

Output
14: label End already defined at ./label.go:11

6.Label和變量名是不沖突的, 可以定義一個名為x的變量和名為x的Label(不過不建議這么用, 這么寫會被人罵的); 而且Label是區分大小寫的.

package main

import (
    "fmt"
)

func main() {
    x := 1
    fmt.Println(x)
    goto x
x:
    fmt.Println(2)
}

 輸出

Output:
1
2

7.變量的聲明必須在goto之前.

package main

import (
    "fmt"
)

func main() {
    goto End
    j := 2
    fmt.Println(j)
End:
    fmt.Println(1)
}

 輸出

Output
goto End jumps over declaration of i at ./label.go:9

這是為什么呢? 因為任何變量的聲明都不能被跳過.

需要改成下面的形式

package main

import (
    "fmt"
)

func main() {
    j := 2
    goto End
    fmt.Println(j)
End:
    fmt.Println(2)
}

二. break(不帶label)

break一般用來跳出最近一層的switchfor, 注意不能用在select

1.單層循環

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
        if i == 3 {
            break
        }
    }
}

 輸出

Output
0
1
2
3

2.雙層循環

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 3; i++ {
        for j := 0; j < 5; j++ {
            fmt.Println("i:", i, ",j:", j)
            if j == 2 {
                break
            }
        }
    }
}

 輸出

Output
i: 0 ,j: 0
i: 0 ,j: 1
i: 0 ,j: 2
i: 1 ,j: 0
i: 1 ,j: 1
i: 1 ,j: 2
i: 2 ,j: 0
i: 2 ,j: 1
i: 2 ,j: 2

從這個例子可以看出break只能跳出最近for

3.對於c/c++來說, switch/case一般都是配合break來使用的.但是在golangswitch/case不需要break就能夠實現和c/c++一樣的效果.

package main

import (
    "fmt"
)

func main() {
    i := 1
    switch {
    case i == 0:
        fmt.Println(i)
    case i == 1:
        fmt.Println(i)
        //break 這里可以使用`break`,但是么有啥效果, 不如不寫
    case i == 2:
        fmt.Println(i)
    }
}

 輸出

Output
1

如果想繼續往下執行, 需要使用fallthrough

package main

import (
    "fmt"
)

func main() {
    i := 1
    switch {
    case i == 0:
        fmt.Println(0)
    case i == 1:
        fmt.Println(1)
        fallthrough
    case i == 2:
        fmt.Println(2)
    }
}

 輸出

Output:
1
2

4.break在函數里是不起作用的, 不能傳遞出來.

package main

func f() {
    break
}

func main() {
    for i := 0; i < 10; i++ {
        f()
    }
}

 輸出

output
4: break is not in a loop

三.break(Label)

break攜帶label可以用在for,switch,select上.

1.對於for/select /switch ,Label必須緊挨着他們.

FirstLoop:
    for i := 0; i < 10; i++ { //invalid break label FirstLoop
    }
    for i := 0; i < 10; i++ {
        break FirstLoop
    }

必須改成這樣

func main() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
    }
FirstLoop:
    for i := 0; i < 10; i++ {
        break FirstLoop
    }
}

對於selectswitch也是一樣.

func main() {
FirstLoop:
    j := 1
    switch j { 
    case 0:
        fmt.Println(0)
    case 1:
        fmt.Println(1)
        break FirstLoop // invalid break label FirstLoop
    }
}

2.一般來說break只能跳出最近一層的forswitch, 但是break Label就可以直接跳出最外面的循環.

func main() {
OuterLoop:
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            fmt.Printf("i=%v, j=%v\n", i, j)
            break OuterLoop
        }
    }
}

Output
i=0, j=0

 輸出

SwitchStatement:
    switch 1 {
    case 1:
        fmt.Println(1)
        for i := 0; i < 10; i++ {
            break SwitchStatement
        }
        fmt.Println(2)
    }
    fmt.Println(3)

 輸出

Output
1
3

四. continue

continue用法基本上和break差不多.1.正常的用法, 調過當前循環, 繼續執行下一次

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 5; i++ {
        if i == 3 {
            continue
        }
        fmt.Println(i)
    }
}

 輸出

Output
0
1
2
4

2.continuelabel一起使用(其實和不使用Label效果一樣)

func main() {
Test:
    for i := 0; i < 5; i++ {
        if i == 3 {
            continue Test
        }
        fmt.Println(i)
    }
}

 輸出

Output
0
1
2
4

3.continue和雙層循環一起使用

OuterLoop:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf(“i=%v, j=%v\n”, i, j)
            continue OuterLoop
        }
    }

 輸出

Output
i=0, j=0
i=1, j=0
i=2, j=0

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM