34

goto is almost universally discouraged. Is using this statement ever worthwhile?

7
  • 18
    xkcd.com/292
    – TheLQ
    Sep 2, 2010 at 23:25
  • 1
    goto is what the cpu ultimately do, but it does not work well with what humans need to comprehend and abstract due to there is no mark on the target end. Compare to Intercal COMEFROM.
    – user1249
    Feb 6, 2012 at 9:57
  • 2
    @ThorbjørnRavnAndersen, what else humans mean when they're talking about state transitions in a state machine? Can't you see a similarity? "Go to a given state", that's what it means and anything else would be nothing but an unnecessary complication of such a trivial thing. And what do you mean by "no mark"? Label is such a mark.
    – SK-logic
    Feb 6, 2012 at 10:10
  • @SK-logic, depends on how far away you will allow goto's to come from. State machines do not require goto to implement.
    – user1249
    Feb 6, 2012 at 10:26
  • @ThorbjørnRavnAndersen, of course goto is not required. It is just the most rational way of implementing them in the imperative languages, since it is the closest thing to the very semantics of the state transition. And its destination can be quite far from the source, it won't hinder the readability. My favourite example of such a code is D.E. Knuth's implementation of the Adventure game.
    – SK-logic
    Feb 6, 2012 at 10:30

14 Answers 14

58

This has been discussed several times on Stack Overflow, and Chris Gillum summarized the possible uses of goto:

Cleanly exiting a function

Often in a function, you may allocate resources and need to exit in multiple places. Programmers can simplify their code by putting the resource cleanup code at the end of the function all all "exit points" of the function would goto the cleanup label. This way, you don't have to write cleanup code at every "exit point" of the function.

Exiting nested loops

If you're in a nested loop and need to break out of all loops, a goto can make this much cleaner and simpler than break statements and if-checks.

Low-level performance improvements

This is only valid in perf-critical code, but goto statements execute very quickly and can give you a boost when moving through a function. This is a double-edged sword, however, because a compiler typically cannot optimize code that contains gotos.

I'd argue, as many others would argue, that in all of these cases, the usage of goto is used as a means to get out of a corner one coded oneself into, and is generally a symptom of code that could be refactored.

17
  • 36
    The first problem is solved very neatly by finally blocks in modern languages, and the second is solved by labelled break s. If you're stuck with C however, goto is pretty much the only way of solving these problems elegantly. Sep 2, 2010 at 22:03
  • 2
    Very good points. I like how Java allows breaking out of multiple levels of loops
    – Casebash
    Sep 2, 2010 at 23:08
  • 7
    @Chinmay - finally blocks only apply to 1) modern languages that have them and b) you can tolerate the overhead (exception handling does have an overhead.) That is, using finally is only valid under those conditions. There are very rare, yet valid situations where a goto is the way to go. Nov 8, 2010 at 17:54
  • 26
    Okay people... what the heck is the difference between break 3 or break myLabel and goto myLabel. Oh that's right just the keyword. If you are using break, continue or some similar keyword you are infact using a goto (If you are using for, while, foreach, do/loop you are using a conditional goto.) Jan 3, 2011 at 3:20
  • 5
    About low level performance - the behaviour of modern processor might be hard to predict (pipeline, out-of-order execution) so probably in 99% of cases it is not worth it or even it might be slower. @MatthewWhited: Scoping. If you enter scope at arbitrary point it is not clear (to human) what constructors should be called (the problem exists in C as well). Feb 6, 2012 at 12:01
59

Higher-level control flow constructs tend to correspond to concepts in the problem domain. An if/else is a decision based on some condition. A loop says to perform some action repeatedly. Even a break statement says "we were doing this repeatedly, but now we need to stop".

A goto statement, on the other hand, tends to correspond to a concept in the running program, not in the problem domain. It says to continue execution at a specified point in the program. Someone reading the code has to infer what that means with respect to the problem domain.

Of course all the higher-level constructs can be defined in terms of gotos and simple conditional branches. That doesn't mean that they're merely gotos in disguise. Think of them as restricted gotos -- and it's the restrictions that make them useful. A break statement is implemented as a jump to the end of the enclosing loop, but it's better thought of as operating on the loop as a whole.

All else being equal, code whose structure reflects that of the problem domain tends to be easier to read and maintain.

There are no cases where a goto statement is absolutely required (there's a theorem to that effect), but there are cases where it can be the least bad solution. Those cases vary from language to language, depending on what higher-level constructs the language supports.

In C, for example, I believe there are three basic scenarios where a goto is appropriate.

  1. Breaking out of a nested loop. This would be unnecessary if the language had a labeled break statement.
  2. Bailing out of a stretch of code (typically a function body) in case of an error or other unexpected event. This would be unnecessary if the language had exceptions.
  3. Implementing an explicit finite state machine. In this case (and, I think, only in this case) a goto corresponds directly to a concept in the problem domain, transitioning from one state to a specified other state, where the current state is represented by which block of code is currently executing.

On the other hand, an explicit finite state machine can also be implemented with a switch statement inside a loop. This has the advantage that every state starts at the same place in the code, which can be useful for debugging, for example.

The main use of a goto in a reasonably modern language (one that supports if/else and loops) is to simulate a control flow construct that's missing from the language.

0
12

The most of the discouragement comes form a sort of "religion" that has been created aroud God Djikstra that was compelling in the early '60s about it's indiscriminate power to:

  • jump anywhere into whatever block of code
    • function not executed from the begining
    • loops not executed from the beginning
    • skipped variable initialization
  • jump away from whatever block of code without any possible cleanup.

This has nothing more to do with the goto statement of the modern languages, whose existence is merely due to support the creation of code structures other than the language provided ones.

In particular the first main point above is anymore permitted and the second is cleaned (if you goto out of a block the stack is unwinded properly and all proper destructors called)

You can refer this answer to have an idea of how even code not using goto can be unreadable. The problem is not goto itself, but the bad use of it.

I can write an entire program without using if, just for. Of course, it will not be well readable, an look clumsy and unnecessarily complicated.

But the problem is not for. It's me.

Things like break, continue, throw, bool needed=true; while(needed) {...}, etc. are noting more than masquerade goto to escape away from the scimitars of the Djikstrarian zealots, that -50 years after the invention of modern laguages- still want their prisoners. They forgot what Djikstra was talking about, they only remember the title of his note (GOTO considered harmful, and it was not even his onw title: it was changed by the editor) and blame and bash, bash and blame every contruct having those 4 letter placed in sequence.

It's 2011: it's time to understand that goto has noting to deal with the GOTO statement Djikstra was compelling about.

2
  • 4
    "Things like break, continue, throw, bool needed=true; while(needed) {...}, etc. are noting more than masquerade goto" I don't agree with that. I would prefer "things like break etc are restricted goto", or something like that. The main problem with goto is that it is usually too powerful. To the extent that the current goto is less powerful than Dijkstra's, your answer is fine with me. Feb 6, 2012 at 12:20
  • 3
    @MuhammadAlkarouri: I totally agree. You just found a better wording to express exactly my concept. My point is that those restriction can sometimes not be applicable and the kind of restriction you need is not in the language. Then a more "powerful" thing, less specialized, is what makes you able to workaround. For example, the Java break n is not available in C++, hence goto escape, even if escape is not required to be just out from the n-ple loop. Feb 6, 2012 at 12:37
11

Surely it depends on the programming language. The main reason goto has been controversial is because of its ill effects that arise when the compiler lets you use it too liberally. Problems can arise, for example, if it lets you use goto in such a way that you can now access an uninitialised variable, or worse, to jump into another method and mess with the call stack. It should be the responsibility of the compiler to disallow nonsensical control flow.

Java has attempted to “solve” this problem by disallowing goto entirely. However, Java lets you use return inside a finally block and thus cause an exception to be inadvertantly swallowed. The same problem is still there: the compiler is not doing its job. Removing goto from the language hasn’t fixed it.

In C#, goto is as safe as break, continue, try/catch/finally and return. It doesn’t let you use uninitialised variables, it doesn’t let you jump out of a finally block, etc. The compiler will complain. This is because it solves the real problem, which is like I said nonsensical control flow. goto doesn’t magically cancel definite-assignment analysis and other reasonable compiler checks.

1
  • Your point is that C#'s goto is not evil? If so, that is the case for every routinely used modern language with a goto construct, not only C#...
    – lvella
    Jun 30, 2015 at 17:42
10

Yes. When your loops are nested several levels deep, goto is the only way of elegantly breaking out of an inner loop. The other option is to set a flag and break out of each loop if that flag satisfies a condition. This is really ugly, and pretty error-prone. In these cases, goto is simply better.

Of course, Java's labelled break statement does the same thing, but without allowing you to jump to an arbitrary point in the code, which solves the problem neatly without allowing the things that make goto evil.

7
  • 6
    goto is never an elegant answer. When your loops are nested several levels deep, your problem is that you failed to architect your code to avoid the multinested loops. Procedure calls are NOT the enemy. (Read the "Lambda: The Ultimate ..." papers.) Using a goto to break out of loops nested several levels deep is putting a band-aid on an open multiple fracture: it may be simple but it isn't the right answer. Dec 18, 2011 at 15:03
  • 10
    And of course, there is never the odd case when deeply nested loops are called for? Being a good programmer isn't just about following the rules, but also about knowing when to break them. Dec 27, 2011 at 13:53
  • 5
    @JohnR.Strohm Never say never. If you use terms like "never" in programming , you've clearly not dealt with corner cases, optimization, resource contraints, etc. In deeply nested loops, goto is very much indeed the most cleanest, elegant way to exit the loops. Doesn't matter how much you've refactored your code. Feb 6, 2016 at 21:34
  • 1
    @JohnR.Strohm: Second most missed feature on switching from VB.NET to C#: the Do loop. Why? Because I can change the one loop that needs a deep break into a Do loop and type Exit Do and there's no GoTo. Nested loops happen all the time. Breaking the stacks happens some % of the time.
    – Joshua
    Jan 22, 2019 at 4:17
  • 2
    @JohnR.Strohm The only reason why you say "goto is never an elegant answer" is because you made your mind up that goto is never an elegant answer, and therefore any solution using goto cannot be an elegant answer.
    – gnasher729
    May 19, 2020 at 21:58
6

The odd goto here or there, so long as it's local to a function, rarely significantly harms readability. It often benefits it by drawing attention to the fact that there's something unusual going on in this code that requires the use of a somewhat uncommon control structure.

If (local) gotos are significantly harming readability, then it's usually a sign that the function containing the goto has become too complex.

The last goto I put into a piece of C code was to build a pair of interlocking loops. It doesn't fit into the normal definition of "acceptable" goto use, but the function ended up significantly smaller and clearer as a result. To avoid the goto would have required a particularly messy violation of DRY.

1
  • 1
    The answer to this is most pithily stated in the old "Lay's Potato Chips" slogan: "Bet you can't eat just one". In your example, you have two "interlocking" (whatever that means, and I'm betting it isn't pretty) loops, and the goto gave you a cheap out. What about the maintenance guy, who has to modify that code after you got hit by a bus? Is the goto going to make his life easier or harder? Do those two loops need rethinking? Dec 18, 2011 at 15:09
3

I think this whole issue has been a case of barking up the wrong tree.

GOTO as such doesn't seem problematic to me, but rather it's very often a symptom of an actual sin: spaghetti code.

If the GOTO causes major crossing of flow control lines then it's bad, period. If it crosses no flow control lines it's harmless. In the grey zone in between we have things like loop bailouts, there are still some languages that haven't added constructs that cover all the legit grey cases.

The only case I've found myself actually using it in many years is the case of the loop where the decision point is in the middle of the loop. You're left with either duplicated code, a flag or a GOTO. I find the GOTO solution the best of the three. There is no crossing of flow control lines here, it's harmless.

5
  • The case you allude to is sometimes dubbed “loop and a half” or “N plus one half loop” and it’ a famous use-case for gotos that jump into a loop (if the language allows this; since the other case, jumping out of the loop in the middle, is usually trivial without goto). Feb 6, 2012 at 16:48
  • (Alas, most languages forbid jumping into a loop.) Feb 6, 2012 at 16:56
  • @KonradRudolph: If you implement the "loop" with GOTO there is no other loop structure to be jumping into. Feb 7, 2012 at 19:34
  • 2
    I think of goto as shouting THE CONTROL FLOW HERE DOESN'T FIT NORMAL STRUCTURED-PROGRAMMING PATTERNS. Because control flows which fit structured programming patterns are easier to reason about than those which don't, one should attempt to use such patterns when possible; if code does fit such patterns, one shouldn't shout that it doesn't. On the other hand, in cases where code really doesn't fit such patterns, shouting about it may be better than pretending the code fits when it really doesn't.
    – supercat
    Mar 27, 2014 at 17:23
  • 1
    @supercat Well, imagine you wrote yourself a schedule, and then the wind blows it out of your hands. According to your logic, you shouldn't retrieve it, because chasing after your schedule wasn't on your schedule. May 19, 2020 at 20:53
1

Yes, the goto can be used to benefit the experience of the developer: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

However, just as with any powerful tool (pointers, multiple inheritance, etc.), one has to be disciplined using it. The example provided in the link uses PHP, which restricts the usage of the goto construct to the same function/method and disables the ability to jump into a new control block (e.g., loop, switch statement, etc.)

1

Depends on the language. It's still widely used in Cobol programming, for example. I've also worked on a Barionet 50 device, whose firmware programming language is an early BASIC dialect that of course requires you to use Goto.

1

It has been mentioned that it's good for exiting nested loops and for cleanups. But I have a case which doesn't fit (at least not perfectly) in any of those cases, even though it's inspired by both. And it also involves the philosophy of single return.

void foo(void *ptr) {
    if(!ptr) goto END;

    while( <condition1> ) {
        // Code
        if( <condition2> ) goto END;
        // Code
    }

END:
    printf("Exiting");
}

In this case, you could use a break in the loop instead. But why? The goto gives more information. A if(condition) break says that we should exit the loop. A if(condition) goto END instead says that we should go to the end of the function and do the remaining part. To me it's clearer.

7
  • I don't see that the goto "gives more information" in these cases. The first jump can be incorporated into an if-block, and the second jump can be converted into a break (if not elided completely by moving the break condition into the while-block condition). And although the label makes the jump target unambiguous, structured blocks are similarly unambiguous. Anyway the risks with gotos do not emerge in such simple examples as these, but only when they form a weave (and thus the order of operations, and the number of paths, becomes increasingly difficult to see).
    – Steve
    Jul 7, 2021 at 6:33
  • @Steve I do not condone weaves of goto. That's where the problem arises.
    – klutt
    Jul 7, 2021 at 7:12
  • What's still not clear is why you would use goto at all, when the simple cases (like yours) are so easily replaced by purely structured blocks? The diktat against gotos, after all, is because they violate the regularity of structured blocks. Neither of your blocks, once entered, actually exit in accordance with the block principle (that is, the execution of a given block is followed by the execution of the first line after the given block).
    – Steve
    Jul 7, 2021 at 9:23
  • And it also involves the philosophy of single return That's the real problem: force-fitting a square algorithm that is simply implemented with multiple return statements into the round hole of "every function may have only one return". "Must cram all algorithms into this one pattern"? Even if they don't fit? You have to make the code more complex just to force-fit it into a rule that's supposedly for making code easier to understand and more maintainable? Jul 7, 2021 at 10:50
  • @AndrewHenle In this case, it's because I want to run the print statement upon exiting.
    – klutt
    Jul 7, 2021 at 10:55
0

goto may be useful when porting legacy assembler code to C. In the first instance, an instruction-by-instruction conversion to C, using goto as a replacement for the assembler's branch instruction, can enable very rapid porting.

2
  • Correct, but one of the arguments against gotos is that they thwart compiler optimizations. May 19, 2020 at 20:46
  • @Sapphire_Brick: Many compiler optimizations are designed around certain execution patterns. If the task to be performed doesn't fit the supported execution patterns, "thwarting" optimizations may not be a bad thing.
    – supercat
    May 19, 2020 at 22:48
0

As an example how moaning about goto can be pointless: I had some lengthy code that asked for gotos in many places jumping past the end of that chunk of code. Unfortunately this was C++. And C++ doesn’t let you goto past any variable initialisation.

Do - while came to the rescue:

do {
    …
    If (condition) break;
    …
    If (condition2) break;
    …
} while (0);

Completely equivalent to using gotos instead of break statements.

2
  • You can skip variable initialization in C++; you just have to skip the entire scope containing that variable. The goto-equivalent could work if you put the code in question in a block. Jul 8, 2021 at 23:07
  • It would seem that what is really missing from structured languages, is the existence of a block (with a specific keyword) whose only purpose for being declared is to allow a jump to its exit point.
    – Steve
    Jul 9, 2021 at 10:26
-2

I would argue no. They should always be replaced with a tool more specific to the problem the goto is being used to solve (unless it's not available in your language). For example, break statements and exceptions solve to previously goto-solved problems of loop escaping and error handling.

6
  • I'd argue that when languages have both these features, goto is typically absent from those languages. Sep 2, 2010 at 22:45
  • But is that because they don't need them, or because people think they don't need them?
    – Michael K
    Nov 4, 2010 at 12:46
  • Your views are bigoted. There are many cases when goto is the closest thing to the very problem domain semantics, anything else would be a dirty hack.
    – SK-logic
    Feb 6, 2012 at 8:56
  • 1
    @SK-logic: I don't think the word "bigoted" means what you think it means. Feb 6, 2012 at 9:51
  • 1
    @Keith, "intolerantly devoted to his or her own opinions and prejudices" - that's what I consistently observe here, with this goto-bashing blindfolded lot. "Should always be replaced" are fanatic's words, at least. Nothing close to a proper, sound opinion, but just a pure bigotry. This "always" does not leave any space for any alternative opinion, see?
    – SK-logic
    Feb 6, 2012 at 10:06
-2

I would say no. If you find the need for using GOTO, I'll bet that there's a need to redesign the code.

4
  • 4
    Maybe, but you haven't provided any reasoning
    – Casebash
    Sep 2, 2010 at 23:09
  • Dijkstra provided the reasoning, in detail, decades ago. Dec 18, 2011 at 15:04
  • 4
    Just Dogma. No resons. Note: Djikstra is NOT ANYMORE A VALID RESON: it was referring of the BASIC or FORTRAN GOTO statement ofn the early '60s. They have nothing to do with the really anemic (compared to the power of those) gots-s of today. Feb 6, 2012 at 8:54
  • @EmilioGaravaglia Well, the part of his reasoning that still applies today is that it's very easy to write spaghetti code by using way to many gotos. However, by that logic, we shouldn't use pointers because using as many pointers as number of gotos needed to create problems would create similar chaos. May 19, 2020 at 20:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.