每个人都知道Dijkstra的《致编辑的信》:goto语句被认为是有害的(这里。html transcript和这里。pdf),从那时起,就有一种强大的推动力,尽可能避免使用goto语句。虽然可以使用goto来生成不可维护的、庞大的代码,但它仍然存在于现代编程语言中。即使Scheme中先进的连续控制结构也可以被描述为复杂的后向。

在什么情况下需要使用goto?什么时候最好避免?

作为一个后续问题:C提供了一对函数setjmp()和longjmp(),它们不仅提供了在当前堆栈帧内进行跳转的能力,还提供了在任何调用帧内进行跳转的能力。这些应该被认为和goto一样危险吗?更危险?


Dijkstra自己也对这个头衔感到后悔,因为这不是他的责任。在EWD1308的结尾(也在这里。pdf),他写道:

Finally a short story for the record. In 1968, the Communications of the ACM published a text of mine under the title "The goto statement considered harmful", which in later years would be most frequently referenced, regrettably, however, often by authors who had seen no more of it than its title, which became a cornerstone of my fame by becoming a template: we would see all sorts of articles under the title "X considered harmful" for almost any X, including one titled "Dijkstra considered harmful". But what had happened? I had submitted a paper under the title "A case against the goto statement", which, in order to speed up its publication, the editor had changed into a "letter to the Editor", and in the process he had given it a new title of his own invention! The editor was Niklaus Wirth.

Donald E. Knuth写了一篇关于这个主题的经典论文,它与Dijkstra的论文相匹配,那就是结构化编程与语句。阅读既有助于重建上下文,也有助于对主题的非教条性理解。在本文中,Dijkstra对这个案例的观点被报道,并且更加强烈:

Donald E. Knuth:我相信通过呈现这样一个 事实上,我并不是不同意 Dijkstra的观点,因为 他最近写道: “请不要落入。 相信我是可怕的 教条的关于[去]的教条的 声明)。我觉得很不舒服 感觉别人在做 宗教出来了,好像 编程的概念问题 只用一个小技巧就能解决,用什么 一种简单的编码纪律!”


当前回答

跳跃的例子在Java字符串类源代码:

int firstUpper;

/* Now check if there are any characters that need to be changed. */
scan: {
    for (firstUpper = 0 ; firstUpper < count; ) {
         char c = value[offset+firstUpper];
         if ((c >= Character.MIN_HIGH_SURROGATE) &&
                 (c <= Character.MAX_HIGH_SURROGATE)) {
             int supplChar = codePointAt(firstUpper);
             if (supplChar != Character.toLowerCase(supplChar)) {
                  break scan;
             }
             firstUpper += Character.charCount(supplChar);
         } else {
             if (c != Character.toLowerCase(c)) {
                  break scan;
             }
             firstUpper++;
         }
     }
     return this;
}
[... subsequent use of firstUpper ...]

这可以用很少的开销重写,例如:

 int firstUpper = indexOfFirstUpper();
 if (firstUpper < 0) return this; 

即使在现代语言中,即使我实际上不喜欢使用gotos,但我认为它们在许多情况下是可以接受的,在像这样的低级情况下,我看起来更好(它不仅仅是退出循环)。

没有激起宗教战争的意图。

其他回答

一个现代的GOTO用法是由c#编译器为yield return定义的枚举器创建状态机。

GOTO应该由编译器而不是程序员使用。

GOTO就像台锯,在采取适当的安全措施时非常有用。

我认为这是有害的,因为大多数初学者都失去了桌子锯和goto的手指。

在某些情况下,这是控制心流的唯一方法,但这些情况是可以避免的。

在我所见过的每个平台上,高级控制结构都被实现为低级的goto(跳转)。例如,Java虚拟机有一个跳转字节码,但是没有if、else、while、For等字节码。

其中一些编译器会为一个简单的条件块创建意大利面条代码。

回答你的问题,去走仍然被那些认为它有害的人认为是有害的。Goto很容易失去结构化编程的优点。

最后,这是你的程序;所以你的决定。我建议在您能够自己回答问题之前不要使用goto,而是在特定问题的上下文中使用。

Goto很有用,这里有一个用c++写的非常强大的开源象棋引擎stockfish的例子。goto只是跳过了一些条件检查(效率增益),如果没有goto语句,程序就必须这样做。如果goto语句标签位于goto声明之后,那么它们就非常无害且可读。

几乎所有可以使用goto的情况,都可以使用其他结构实现相同的效果。无论如何,编译器都会使用Goto。

我个人从来没有明确地使用它,也不需要。