golang中goto跳转语句和跳转标签声明
  gOfhOzgl2UPX 2023年11月13日 16 0

和很多其它语言一样,Go也支持goto跳转语句。 在一个goto跳转语句中,goto关键字后必须跟随一个表明跳转到何处的跳转标签。 我们使用LabelName:这样的形式来声明一个名为LabelName的跳转标签,其中LabelName必须为一个标识符。 一个不为空标识符的跳转标签声明后必须被使用至少一次。

一条跳转标签声明之后必须立即跟随一条语句。 如果此声明的跳转标签使用在一条goto语句中,则当此条goto语句被执行的时候,执行将跳转到此跳转标签声明后跟随的语句。

一个跳转标签必须声明在一个函数体内,此跳转标签的使用可以在此跳转标签的声明之后或者之前,但是此跳转标签的使用不能出现在此跳转标签声明所处的最内层代码块之外。

下面这个例子使用跳转标签声明和goto跳转语句来实现了一个循环:

package main

import "fmt"

func main() {
    i := 0

Next: // 跳转标签声明
    fmt.Println(i)
    i++
    if i < 5 {
        goto Next // 跳转
    }
}

上面刚提到了一个跳转标签的使用不能出现在此跳转标签声明所处的最内层代码块之外,所以下面的代码片段中的跳转标签使用都是不合法的。

package main

func main() {
goto Label1 // error
    {
        Label1:
        goto Label2 // error
    }
    {
        Label2:
    }
}

 

另外要注意的一点是,如果一个跳转标签声明在某个变量的作用域内,则此跳转标签的使用不能出现在此变量的声明之前。 关于变量的作用域,请阅读后面的文章代码块和作用域

下面这个程序编译不通过:

package main

import "fmt"

func main() {
    i := 0
Next:
    if i >= 5 {
        // error: goto Exit jumps over declaration of k
        goto Exit
    }

    k := i + i
    fmt.Println(k)
    i++
    goto Next
Exit: // 此标签声明在k的作用域内,但
      // 它的使用在k的作用域之外。
}

刚提到的这条规则可能会在今后放宽。 目前,有两种途径可以对上面的程序略加修改以使之编译通过。

第一种途径是缩小变量k的作用域:

func main() {
    i := 0
Next:
    if i >= 5 {
        goto Exit
    }
    // 创建一个显式代码块以缩小k的作用域。
    {
        k := i + i
        fmt.Println(k)
    }
    i++
    goto Next
Exit:
}

第二种途径是放大变量k的作用域:

func main() {
    var k int // 将变量k的声明移到此处。
    i := 0
Next:
    if i >= 5 {
        goto Exit
    }

    k = i + i
    fmt.Println(k)
    i++
    goto Next
Exit:
}

包含跳转标签的breakcontinue语句

一个goto语句必须包含一个跳转标签名。 一个break或者continue语句也可以包含一个跳转标签名,但此跳转标签名是可选的。 包含跳转标签名的break语句一般用于跳出外层的嵌套可跳出流程控制代码块。 包含跳转标签名的continue语句一般用于提前结束外层的嵌套循环流程控制代码块的当前循环步。

如果一条break语句中包含一个跳转标签名,则此跳转标签必须刚好声明在一个包含此break语句的可跳出流程控制代码块之前。 我们可以把此跳转标签名看作是其后紧跟随的可跳出流程控制代码块的名称。 此break语句将立即结束此可跳出流程控制代码块的执行。

如果一条continue语句中包含一个跳转标签名,则此跳转标签必须刚好声明在一个包含此continue语句的循环流程控制代码块之前。 我们可以把此跳转标签名看作是其后紧跟随的循环流程控制代码块的名称。 此continue语句将提前结束此循环流程控制代码块的当前步的执行。

下面是一个使用了包含跳转标签名的breakcontinue语句的例子。

package main

import "fmt"

func FindSmallestPrimeLargerThan(n int) int {
Outer:
    for n++; ; n++{
        for i := 2; ; i++ {
            switch {
            case i * i > n:
                break Outer
            case n % i == 0:
                continue Outer
            }
        }
    }
    return n
}

func main() {
    for i := 90; i < 100; i++ {
        n := FindSmallestPrimeLargerThan(i)
        fmt.Print("最小的比", i, "大的素数为", n)
        fmt.Println()
    }
}

 

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

推荐阅读
gOfhOzgl2UPX