为什么 Go 有“ goto”语句?

我很惊讶地发现 Go 有一个 ‘ goto’语句。我一直被教导“ goto”语句是过去的事情,因为它阻碍了程序的实际流程,而函数或方法总是控制流程的更好方法。

我一定是漏掉了什么,为什么谷歌会把它加进来?

65452 次浏览

Goto 是一个好主意,当没有一个内置的控制特性可以完成你想要的任务,当你可以用 Goto 表达你想要的任务时。(在某些语言中,如果你没有 Goto,那就太可惜了。你最终会滥用一些控制功能,使用布尔标志,或者使用其他比 goto 更糟糕的解决方案。)

如果其他一些控件特性(以一种相当明显的方式使用)可以满足您的需要,那么您应该优先使用它来进行转换。如果没有,大胆使用 goto!

最后,值得注意的是,Go 的 goto 有一些限制,旨在避免一些模糊的错误。请参见 说明书中的这些限制。

当我们实际检查 Go 标准库的源代码时,我们可以看到 goto实际上在哪些地方得到了很好的应用。

例如,在 math/gamma.go文件中,使用 goto语句:

  for x < 0 {
if x > -1e-09 {
goto small
}
z = z / x
x = x + 1
}
for x < 2 {
if x < 1e-09 {
goto small
}
z = z / x
x = x + 1
}


if x == 2 {
return z
}


x = x - 2
p = (((((x*_gamP[0]+_gamP[1])*x+_gamP[2])*x+_gamP[3])*x+_gamP[4])*x+_gamP[5])*x + _gamP[6]
q = ((((((x*_gamQ[0]+_gamQ[1])*x+_gamQ[2])*x+_gamQ[3])*x+_gamQ[4])*x+_gamQ[5])*x+_gamQ[6])*x + _gamQ[7]
return z * p / q


small:
if x == 0 {
return Inf(1)
}
return z / ((1 + Euler*x) * x)
}

在这种情况下,goto使我们免于引入另一个(布尔型)变量,这个变量仅用于控制流,在最后检查。在这种情况下goto语句实际上使代码更易于阅读和遵循(与您提到的针对 goto的参数完全相反)。

还要注意,goto语句有一个非常特定的用例。关于 goto 的语言规范声明它不能跳过进入作用域的变量(被声明) ,也不能跳到其他(代码 -)块。

自从上世纪60年代和70年代 意大利面密码时代以来,Goto 的声明受到了很多质疑。那时候程序设计方法学非常贫穷。然而,Goto 并不是天生的邪恶,当然,它也可能被懒惰或不熟练的程序员滥用和滥用。滥用 Gotos 的许多问题可以通过开发过程(如团队代码审查)来解决。

goto是以与 continuebreakreturn相同的技术方式跳跃。有人可能会争辩说,这些言论同样是邪恶的,但事实并非如此。

Go 团队之所以包含 Gotos,可能是因为它是一个常见的流控原语。此外,他们希望得出结论,围棋的范围排除了使白痴安全的语言不可能被滥用。