Go语言学习指南:惯例模式与编程实践
上QQ阅读APP看书,第一时间看更新

4.7 goto语句

goto是Go中的第4个控制语句。自从Edgar Dijkstra在1968年写了“Go To Statement Considered Harmful”(https://oreil.ly/YK2tl),goto语句便成为编程家族的害群之马。这确实是显而易见的。常规上,goto是危险的,因为它可以跳转到程序中的几乎任何地方,可以跳进或跳出循环,跳过变量定义,或者进入if语句代码块中。使用了goto的代码让人难以理解代码的真正意图。

大多数现代语言不包含goto语句。尽管Go有goto语句,但你应该尽量避免使用它。不过它有一些用途,在Go中它适合结构化编程。

在Go中,goto语句指定一个指向代码行的标签,然后执行跳转到该行。然而,你不能在任何地方跳转。Go语言禁止跳过变量声明、跳转到内部或平行代码块。

示例4-23中的程序显示了两个非法的goto语句。你可以在The Go Playground(https://oreil.ly/l016p)上运行它。

示例4-23:goto的规则

尝试运行此程序会产生以下错误:

那么,应该如何使用goto呢?如果确实需要使用,建议标记在breakcontinue语句处,这样允许程序执行跳出深度嵌套循环或跳过迭代。示例4-24中就展示了这样的作用,这是少数有效的用例之一。

示例4-24:使用goto

这个例子是人为设计的,展示了如何使用goto语句让程序更清晰。在简单例子中,有一些特定需要是,我们不想执行函数中的部分代码,但又想执行到函数的结尾处。其实有很多方法可以不使用goto就能做到这一点。我们可以在for语句之后使用一个布尔判定,或者将复杂的代码复制到for循环结束的逻辑中,而不是使用goto,但是这两种方法都有缺点。在代码中使用布尔标记来控制逻辑流与goto语句具有相同的功能,只是更冗长。复制复杂的代码会使代码更难维护。这些情况很少见,在没有更好的选择时,goto语句可以提升代码可读性,也是不错的选择。

这里有一个真实的例子,你可以进入标准库中的strconv包,看一下文件atof.go中的floatBits方法。由于它太长了,不能完整地展示,但该方法以以下代码结束:

在这些代码之前有几个条件检查。有些情况需要运行overflow标签之后的代码,而其他情况则需要跳过该代码并直接转到out。根据条件的不同,有些逻辑使用goto跳转到overflow标签处,有一些则跳转到out标签处。尽管可以对这些代码进行改进,避免使用goto语句,但是这样会使代码更难理解。

 尽量避免使用goto,但是在极少情况下,它确实可以让代码的可读性更好,也是一个不错的选择。