Go 中的标签

saberuster · 2018-05-06 22:11:44 · 6941 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2018-05-06 22:11:44 的文章,其中的信息可能已经有所发展或是发生改变。

Labelbreakcontinue 语句中是可选参数,而在 goto 语句中是必传的参数。Label 只在声明它的函数中有效。只要函数中声明了 Label ,那它在该函数的整个作用域都有效。

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

(注意!我们是在 goto 语句之后定义的 Label

> ./bin/sandbox
1
3

这里所指的作用域不包括嵌套函数的作用域:

    func() {
        fmt.Println(“Nested function”)
        goto End
    }()
End:

上面这段代码在编译时会报 label End not defined 错误。除此之外还会报:label End defined and not used,因为我们需要保证只声明需要使用的 Label

Label 中没有块作用域的概念。所以不能在嵌套的块作用域中声明重复的 Label

    goto X
X:
    {
        X:
    }

编译上面的代码会报错提示 Label 已经存在了。

Label 的标识符和其他标识符具有不同的命名空间,所以不会与变量标识符等发生冲突。下面这段代码同时在 Label 和变量声明中都使用 x 作为标识符:

    x := 1
    goto x
x:
    fmt.Println(x)

break 语句

break 语句一般都是用来跳出 forswitch 语句。在 Go 中也可以在 select 语句中使用 break

对于拥有类 C 语言编程经验的人肯定知道每个 case 语句都需要以 break 结尾。但是在大多数情况下程序都不希望执行到下一个 case 语句中。在 Go 中恰恰相反,如果需要执行下一个分句的代码可以使用 fallthrough 语句:

switch 1 {
case 1:
    fmt.Println(1)
case 2:
    fmt.Println(2)
}
> ./bin/sandbox
1
switch 1 {
case 1:
    fmt.Println(1)
    fallthrough
case 2:
    fmt.Println(2)
}
> ./bin/sandbox
1
2

fallthrough 只能作为一个分句的最后一条语句使用。

break 语句不能跨越函数边界。

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

上面的代码会报 break is not in a loop 错误。

一般情况下,break 可以用来跳出 forswitchselect 语句。使用 Labelbreak 可以做更多的事情。

break 语句的 Label 必须对应围绕 breakforswitchselect 语句。所以下面的代码不能通过编译:

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

它会报 invalid break label FirstLoop 。因为 Label 不在 break 对应的循环上。

break 可以跳出嵌套的循环:

OuterLoop:
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            fmt.Printf(“i=%v, j=%v\n”, i, j)
            break OuterLoop
        }
    }
> ./bin/sandbox
i=0, j=0

如果 break 像下面这样用,那它不仅仅是退出 for 循环:

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

break 可以在 forswitchselect 语句中的任何地方退出并切换到指定 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/sandbox
i=0, j=0
i=1, j=0
i=2, j=0

goto 语句

goto 语句可以让程序切换到某个被 Label 标记的地方继续执行。

    i := 0
Start:
    fmt.Println(i)
    if i > 2 {
        goto End
    } else {
        i += 1
        goto Start
    }
End:

(注意:End 可以为空)

breakcontinue 语句不同,goto 语句必须指定 Label

goto 只能让程序移动到相同函数的某个位置。因此在执行 goto 的时候还有另外两条规则:

  • 不能跳过变量声明,如果 goto 跳过,编译器会报 goto Done jumps over declaration of v at…
    goto Done
    v := 0
Done:
    fmt.Println(v)
  • goto 不能切换到其他代码块,如果切换,编译器会报 goto Block jumps into block starting at …
goto Block
{
Block:
    v := 0
    fmt.Println(v)
}

via: https://medium.com/golangspec/labels-in-go-4ffd81932339

作者:Michał Łowicki  译者:saberuster  校对:polaris1119

本文由 GCTT 原创编译,Go语言中文网 荣誉推出


有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

6941 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传