【SCRY技术分享】Go语言中goto的总结

【SCRY技术分享】Go语言中goto的总结插图1

前言

Goto语句又称为无条件转移语句。这里就要谈谈什么是条件转移语句了,正常来说代码执行应当是从入口开始,从上至下依次执行,完成特定的功能后返回结果,为了完成复杂的逻辑判断我们引入了判断结构,循环结构等控制结构(本质上也是goto的变种),当然不同的语言相同结构在语法上可能有些许差异。代码在这些结构中的运行是必须满足特定的条件才能跳转进入执行或者退出。然而goto语句没有这个要求,它会使得代码直接跳转到指定的位置,无规则可言。

在结构化程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,大大降低程序的结构性和可读性,使理解和调试程序都产生困难,虽然目前主流语言都保留了goto关键字,但实际使用都会受到严格控制。就我个人观点而言,在某些复杂的逻辑嵌套中,使用goto往往会更加简洁或提高程序的效率,但一定不要滥用。

1.Golang对goto语句的使用限制:

1.1.禁止跨函数跳转,以下代码是错误的。

func example() {	goto Loop}func main() {	example()Loop:}

1.2.执行goto语句不会使任何变量进入goto的作用域,以下代码是错误的,n无法执行声明初始化。

goto Loop	var n int64Loop:	fmt.Println(n)

1.3.块外的goto语句不能跳转到块内的标签。

var n intif n%2 == 1 {	goto Loop}for n > 0 {	n--Loop:	n--}

1.4.goto与label之间不能有变量声明过程,无论是var关键字还是:=简写均不行,目的是为了防止后续代码有关中有关于这些变量的使用。

if err != nil {      goto PrintErr   }  var m intN:=0PrintErr:   println(err)

通过对上述三种情况进行分析我们可以得出一个结论,在go中goto的跳转只有一种使用情况:在一个函数体内,从块内跳转到块的外层。

2.Goto适用场景

2.1.跳出n层循环,避免多次break。

/    for {         for {             for {                 goto }         }     } : }//使用return,但是只能适用于结束循环立即返回值的情况func example() {     for {         for {             for {                 return             }         }     } }//以上两种方案均避免了多次使用break

2.2.增加程序的可读性,简化写法。当程序逻辑单独使用条件或者循环等语句都不方便表达时通过适当的goto简化逻辑。这是标准库math/gamma.go里的代码片段(有简化):

for x < 0 {         if x > -1e-09 {             goto }         f()     }     for x < 2 {         if x < 1e-09 {             goto }f()     }     if x == 2 {         return z     }     x = x - 2     f()     return z * p / q :     if x == 0 {         return Inf(1)     }     return z / ((1 + Euler*x) * x)

2.3.集中处理错误,多处错误处理存在代码重复时是非常棘手的。

err := firstCheckError()    if err != nil {       goto }    err = secondCheckError()    if err != nil {       goto }    return :    fmt.Println(err)    exitProcess()

2.4.出错时清理资源(不推荐使用),go中defer关键字可以代替实现且可读性更高。

func deferDemo() {     err = createResource1()     if err != ERR_SUCC {         goto }     err = createResource2()     if err != ERR_SUCC {         goto }     err = createResource3()     if err != ERR_SUCC {         goto }     return ERR_SUCC :     destroyResource2() :     destroyResource1() :     return ERR_FAIL

扩展,关于go逻辑分支实现。

BranchStmt struct {    Tok   token // Break, Continue, Fallthrough, or Goto    Label *Name    // Target is the continuation of the control flow after executing    // the branch; it is computed by the parser if CheckBranches is set.    // Target is a *LabeledStmt for gotos, and a *SwitchStmt, *SelectStmt,    // or *ForStmt for breaks and continues, depending on the context of    // the branch. Target is not set for fallthroughs.    Target Stmt    stmt }

这里的tok是goto关键字的唯一标识,stmt是位置信息。

举报/反馈

原创文章 【SCRY技术分享】Go语言中goto的总结,版权所有
如若转载,请注明出处:https://www.itxiaozhan.cn/20229494.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注