Go To

The apprentice uses it without thinking. The journeyman avoids it without thinking. The master uses it thoughtfully.

The descent to Hades is the same from every place. -- Anaxagoras

MachineLanguage uses it except it is called a Jump, Subroutines use it except it returns (to a place, or with a value), Browsers use them, but they are called Links. It is like BasicLanguage, forever the target of those who point to both as failed processes, but both linger on regardless! Note that pointing is in itself a Goto for focus of attention or for the eyes.

With Goto's:

  if (foo) then goto hell

Without Goto's:

  going_to_heaven = true  // innocent until proven guilty
  while loop_stuff and going_to_heaven
...
if (foo) then going_to_heaven = false
...
  end while
  if (not going_to_heaven and zoob)
...
  end if
  ...
  if (not going_to_heaven or groob)
...
  end if
  // final
  if (not going_to_heaven)
hell()
  end if

Some semi-goto fans say that no goto's sometimes results in "flaggy code". See FlagsAreSelfModifyingCode

Flaggy code is easier to modify than SpaghettiCode as long as flag are meaningful.

I don't know if I agree with that as a general statement. It depends on the style of goto-ing.

Code with exceptions but no gotos:

try {
if (foo) throw DamnedException?;
/* much more code */
} catch (DammedException? &d) {
 Hell(d)
}

{Every experienced programmer that has programmed for a long time (such as Linus, BSD developers, and others) knows of the structured clear use for GoTo's. Those that argue that flags are always better are simply religious unexperienced zealots who do not realize that goto can be a form of encapsulation, a patterned clear way of exiting structurally, and most importantly a more readable and maintainable way of exiting. Furthermore, some don't realize that Exit, Break, and Return calls are just limited forms of goto, just as an error label is a clean limited form of goto (exit with error). GoodUseOfGoto will note patterns of where GoTo can be useful (when used with discipline).}

GoTo should be used only to point to an oubliette, i.e. a SinkState? in which we need no memory of the SourceState?. GoTo is the simplest and least obfuscated way to transition into such a state, since it conveys no extra information besides the terminus. Once we're in Hell, we don't care where we came from or how we got there, just the fact that we ended up there. If there is only one such SinkState? (or a very small number of them, say less than three), this usage is NotConsideredHarmful. -- JosephTurian


Arguments for GoTo:

Arguments against Goto:

most Goto defenders have died - Well, LinusTorvalds is alive and well. Blocks offer visual cues about flow - That's why one should use them were appropriate. Unfortunately, they are not always appropriate, and using blocks sometimes leads to "flaggy" code that is often much more confusing than (you named it) a simple goto.

In fact, languages like Java use all sorts of "restricted gotos" even though they don't like to admit it. Take the return, continue and break statements, for instance. Even case labels are actually a sort of conditional goto. Hypothetical example:

 bool login(User user) {
 if (!users.contains(user))
 return false;

String password = promptForPassword(); if (!checkPassword(user, password)) return false;

String shell = getShell(user); if (!allowedShells.contains(shell)) return false;

log("User " + user + " logged in."); return true; }

Now consider the same without permitting the return statement (return value is assigned to "login", and the function returns ONLY at the end of the block):

 bool login(User user) {
 if (users.contains(user)) {
 String password = promptForPassword();
 if (checkPassword(user, password)) {
 String shell = getShell(user);
 if (allowedShells.contains(shell)) {
  log("User " + user + " logged in.");
 login = true;
 } else
 login = false;
 } else
 login = false;
 } else
login = false;
 }

 bool login(User user) {
login = false;
 if (users.contains(user)) {
 String password = promptForPassword();
 if (checkPassword(user, password)) {
 String shell = getShell(user);
 if (allowedShells.contains(shell)) {
  log("User " + user + " logged in.");
 login = true;
 }
 }
 }
 }

(i don't know java, only C)

 bool login(User *user){
string password,shell;
 bool login;
if(login=set_contains(user,users)&&
 (password=promptForPassword(),checkPassword(user,password))&&
 (shell=getShell(user),set_contains(shell,allowedShells)))
 printf("User %s logged in.\n",user);
 //additional processing using password and shell
 return login;
 }

Is that much better? I doubt it. When we add some more conditions, it can actually be much worse. Add some loops and all hell breaks loose - now we need flags to test for extraordinary termination of everyone of those loops. (See a possibly clearer idiom for short circuit flag testing below)

I prefer structured statements over gotos where possible. But I've found that gotos are actually the best solution in some situations. For example, state machines, like a hand-coded lexer:

 while (!eof()) {
 char c = nextchar();
 switch (state) {
 case state_foo:
 switch (c) {
 case '/':
 state = state_bar;
 continue; // swallow '/' and switch to state_bar
 case '_':
 state = state_baz;
 goto state_baz; // do not swallow '_', and switch to state_baz
 }
 break;
 case state_bar:
 // ...
 case state_baz:
 state_baz:
 // ...
 }
 }

-- ArneVogel


ConsideredHarmful.

(then, ComeFrom should be ConsideredHelpful?!)


It is highly debatable whether a new object-oriented procedural language should contain a goto statement. Most languages in use today either have a goto (C++) or at least have a reserved word for it (Java).


If it is ConsideredHarmful, don't call it a GoTo... call it "Hyperlink"

What makes it "harmful" isn't what it is called.


... but... hyperlinks know where they came from and return, like function calls.

Would anyone like to share my complaint that pointers are "data goto's", ie they goto somewhere in a field or structure without keeping either a "return" reference ("where this reference came from") or a justification? One failure of "goto's" is that they simply do their thing without explaining why, as a loop or if statement would, and ISTM that pointers don't explain why they are referencing things either...

-- DavidWolff?

The pointer and function that uses the pointer are similar to a hyperlink and a browser that gives access to it: it is the function, and the browser, not the pointer, or the link, who is given responsibility for acquiring past state.

-- PanuKalliokoski

Hyperlinks in an undirected graph are (from, to) ordered pairs, but on the web they are just (to) singletons because the web is a directed graph. Pointers are similarly directed. It's better to have directed primitives than undirected because you can build an undirected graph out of a directed graph provided you can enforce the constraint that any directed edge between vertex V1 and V2 has a corresponding directed edge between vertex V2 and V1.

All that you know, but actually enforcing it is difficult. It's actually impossible on the web because you can't control the other vertex (it is possible on localized subgraphs of the web like Wiki, though, because you can control both vertices). You can also control pointers like this, if you work at it. Some languages might get you where you want to go as well (not that I know of any), although it would severely violate encapsulation. Not like that matters, anyway.

It's an interesting idea. Two questions: 1. How would you implemented an undirected pointer? 2. What would be the advantage(s)? -- SunirShah

A bidirectional pointer is a relation, so a relational database is probably what you're looking for.


I don't think that the fact that GoTo's don't remember where they came from is what makes GoTo's harmful. Consider tail calls, which also don't remember where they came from. The problem with GoTo is (IMNSHO) that it drags all kind of state from the "sender" to the "receiver". This, in turn, allows the "receiver" to depend on the state of the local variables as set by the "sender". And this in turn allows the classic spaghetti code style where there are 20 global "flag" variables which somehow describe the program's state while we are GoTo-ing around.

So I would argue that GoTo essentially gives you the same power as tail calls with dynamically scoped (or global) variables, and that the problem is in the dynamically scoped variable functionality of GoTo, not in the tail call functionality.

-- StephanHouben


Ah, I wish there was a 'break(n)' in C/C++ (to get out of more than one loop at once). -- PierrePhaneuf

It doesn't work well. It's not very readable. Readers have to count the number of loops to figure out where it goes to, and counting is not work for humans. Especially as you can't just count braces. A second problem is that it's fragile. If the code is edited to add another loop, the break(n) may need to be updated.

Where possible, it is better to put the loops into a function and then return from the function. Only the innermost loops will be time-critical, so we don't care about the overhead of the function call around the outer loop. If this isn't possible, a goto will be clearer than break(n). -- DaveHarris

It's true that humans shouldn't do the counting, and 'break(n)' is probably bad. But I seem to remember seeing a 'break label ' statement in some language. (C++? Gave up on it years ago.) This is just like a goto, with the advantage of being structured. -- CraigPutnam

Java has 'break label'.

All 8-bit BasicLanguage implementations had nested FOR loops, and most of them allowed you to escape a level like this:

  10 FOR X=1 to 10
  20 FOR Y=1 to 10
  30 GOSUB 4000
  40 IF Z>5 THEN NEXT X
  50 NEXT Y
  60 NEXT X

The above might have caused instability in the stack on some systems, though.

If you yearn for structured GoTo, sometimes continuations (CallWithCurrentContinuation) is what you need. Exceptions are also a subcase of first-class continuations. -- PanuKalliokoski

Simple implementation of goto using CallWithCurrentContinuation, in ruby:

 def goto(cont)
cont.call(cont) 
 end

label= callcc {|cc| cc} puts 'in a loop mood' goto label exit!
Note that even if this may sound awful it is still better than a standard GoTo, in that you can explicitly handle labels at runtime.

Knuth has a famous paper called StructuredProgrammingWithGoToStatements arguing for where GoTo can be profitably used. It is under copyright, but appropriate Google searches can generally find a scanned in pdf version. Most of his examples show algorithms that can be more efficiently implemented with GoTo than without. However he notes on page 277 a theorem by Kosaraju that in a language with loop control and named loops you can implement any algorithm that you can implement with GoTo with no loss of efficiency. In such languages (Java, Perl, etc) the vast majority of GoTo's that make sense in languages like C and C++ can be eliminated. The corollary, of course, is that named loop control is just as abusible as GoTo. The right question is whether people tend to abuse them as badly. The answer is "no" for reasons I intend to explain at InternalLoopExitsAreOk. -- BenTilly


Some consider a goto less bad if its usage is limited (either self-imposed by the programmer or enforced by the language): A goto statement as a goto label, where label is only allowed to be in the current method. If all methods are less than 50 lines long, and they limit themselves to only one or two goto labels, then goto's shouldn't be so spaghetti inducing.


But most fresh programmers now know that they shouldn't use it, they just don't understand why. They're now perfectly capable of producing bad code without the use of the 'goto' statement. And, I note that everyone seems happy to fight against the 'goto' but are all for the exception - a construct with all the same problems as the 'goto'. -- ArnoldLayne

I think of raising an exception as a GoTo and handling one as a matching ComeFrom statement. Usually, you'll have a better explanation of an exception than you'll have of a goto. So what's the problem with them?

Exceptions aren't at all like that. A catch block is a "ComeWhen?", and a throw statement is just "Go". ArneVogel


Can you imagine the harmfulness of the directed goto (used in Fortran)

 On N Goto(1000,1200,3200,1534,1600)
[Perhaps you mean a computed goto - GOTO (1000,1200,3200,1534,1600),N]

When encountered in a digitizing program I was making changes in - I gave up trying to trace the code and rewrote the whole program.

Not as bad as at least one BASIC had:

 GOTO 1000+(N*100)


I got my first paying programming job in part because I wrote a program that productively used parameter substitution in labels. -- WardCunningham

  goto $var
  a$par1: something
  b$par2: something else


The FortranLanguage example isn't harmful in itself, but enables a mess to be constructed, and may encourage overlong code by discouraging subprograms. The BASIC example looks absurd, but I once had to do something similar to optimize space usage in an assembler program which had to occupy very limited space.


I was once in a JavaLanguage discussion about whether we should use a return value with an if statement or an exception. Both seemed klunky to us. The conversation turned to the similarity of Java's try-catch and SwitchStatements. Then out of the blue, it became obvious that the ability to throw an exception from any point in a java program and catch it at any other arbitrary point later looked a lot like GoTo. Obviously, there are differences: the "Go" and "To" are not specified in the same place, which is very flexible, however on the whole JavaExceptions? are not as flexible as GoTo. We both could cite C code examples in which we used GoTo for situations where we would very likely use exceptions in java. -- EricHerman


I once kicked around the idea of trying to "objectively" figure out why excess goto's are annoying (to me). I could not come up with anything concrete. The best I could come up with is that nested blocks make the design more *consistent* from programmer to programmer. (I don't know if one could make an acceptable consistency metric.) It seems some programmers indeed did have certain 'goto patterns' that they got comfortable with, but these were generally not documented. It would be interesting to see the best arguments put forth by 'goto fans'.

The most "objective" argument I have seen to date is that nested block indentation provides visual clues to the flow, while goto's generally don't. I saw this argument on c2.com somewhere, but forgot where.

Anyhow I find it odd that there is no clear-cut "proof" that goto's are "bad". Makes an interesting delema IMO. It is something that most people agree with, but lacks objective evidence beyond a mere vote count. (EmpiricalEvidence)

I've been working in a language that not only has the single goto statement, but indexed goto statements, and even a noreturn statement if you are mental enough. Some of the code in there is a real mess. When you have to maintain a system that is jumping in about 30 different places across 5 different source files, it becomes a nightmare. With functions, unless you end up trapping an error, you are guaranteed to come back. (that is, unless someone sneeks in a noreturn). With goto statements, you never know where you are going to end up next, and you end up having code that is full of bookmarks just so you can try and keep track of what is going on.

You did hit the nail on the head. Gotos not only do not provide visual clues, but they obfuscate code flow. -- JonathanArkell

Visual clues are relatively objective to study, but "obfuscate", similar to "messy", is damned hard to measure and often seems subjective. Things which confuse the daylights out of me are simple for others, and visa versa. I assume that "lacks consistency" is easier to measure, or at least more concise, than "messy", but may be wrong.


I find it hilarious that we've spent 25 years gradually recognizing that goto's generally are bad (with the exception of being able to leave nested loops as noticed above). And now the next big programming language C# has re-introduced the goto... ;-) what will be the next move, I ponder - making the goto a first-class entity? :-)

Kasper B. Graversen

I suspect C# kept it for backward-compatibility reasons. There are a lot of algorithms floating around written in C.

"Systems-level" languages like C#, Java, or C will always have gotos for two reasons. First, gotos map directly to jump instructions. In some cases, efficiency really is important; while other constructs like flag variables, exceptions, or state machines will get you the same behavior, they wouldn't be nearly as efficient. Second, even though gotos make code hard to read, they are theoretically well understood. Thus when you are automatically generating code -- which rarely needs to be read or understood, anyway -- gotos are a natural choice; it's much easier to convert structured code to gotos rather than from gotos to structured code.

These two reasons are why you may see gotos in the generated code from lex/yacc-style tools, which need to be fast and direct. Theoretically, you don't need gotos, but they are invaluable in a few practical applications.


[From GoTos]

I like gotos. My teacher doesn't.

They're like hand grenades. Sure, they're powerful, but they can kill you. Your teacher is looking at different issues than you are.

When I took C programming I had a great teacher who really harped on good consistent style for maintainability. He clearly gave the reasons for avoiding the goto statement and essentially presented it as a relic. We stayed in touch, and several years later I e-mailed him to talk about the large number of goto statements in Linux kernel source. His response was that if you can justify it, then it's ok. In highly optimised low level code (like an OS kernel) it might be justified.


It should be noted as well that the GoTo statement in C/C++ (and I assume C#) is considerably defanged compared to the GoTo statement that existed in early unstructured languages (BasicLanguage, FortranLanguage, CobolLanguage, etc.). Using the C/C++ goto, one cannot:

In other languages, you could GoTo wherever you wanted and whenever you wanted--including in manners which were truly hideous. That is the sort of stuff which caused claims of GotoConsideredHarmful. While C gotos can be misused; in practice they usually aren't--the most common use of goto in C/C++ that I ever see is exiting deeply nested control structures; a use which is relatively benign.

CeePlusPlus does not prevent you from jumping into the middle of a block, provided you don't skip any variable declarations. -- ArneVogel


Thought I'd present an example of what I feel is a reasonable goto use (in C++) that isn't the usual nested escape. First, the setup... a GUI program which draws overlays, originally defined by a bitmask. I'm adding vector definitions as well and writing the code for drawing vector points (yes, in the app this is different from a bit mask). Anyway...

Mask *pMask(NULL); switch (type) {

case POINT:

Mask tmpMask;
vector<Location> &v=getVectorOfPoints();
for (iterator it=v.begin();it!=v.end();++it)
tmpMask.set(*it);
pMask = &tmpMask;
goto drawMask;
case MASK:
pMask=getBitMask();

drawMask:

// here's the code to draw the mask overlay
break;

}

Now, I could have moved the mask drawing code to another function but this would have meant passing lots of other variables to the other function, or making them all member of the class neither of which made much sense or cleanliness. The drawing code is about 50 lines...too much to duplicate and expect maintainability. Another alternative is to fall thru into case MASK and wrap the getBitMask() call in an if(type==MASK) but now case MASK needs to know that another case might be using it...as we know, this kind of relationship is iffy at best. My rules for gotos:

1) do the alternatives lead to worse looking/harder to maintain code than the goto 2) does the goto lead to an execution flow that makes sense and is absolutely free of nasty side effects 3) the label absolutely MUST either exist on the same "screen" (I usually assume an editor screen is about 30 or so lines high...reasonable these days) as the goto or just outside a clearly defined block (I.E. nested loops)

Hope this gives you something more to think about.


Oh come on...is anyone really arguing about whether goto should ever be used? Of course it has its uses, just like for or while or practically any other programming construct. I use it all the time, for one specific idiom. This is in PerlLanguage, but also occurs in CeeLanguage etc:

 EDIT: system($editor, $temp_file);
if($? == -1) {
print "Could not execute editor ($editor): $!\nAborting, no changes made.";
exit(1);
}
 ASK: print "Proceed with update? [Y]es [No] [E]dit again > ";
my $answer = <STDIN>;
chomp $answer;
if($answer eq "E") { goto EDIT; }
elsif($answer eq "N") { print "Cancelled.\n"; exit(0); }
elsif($answer ne "Y") { goto ASK; }
# if we get here, that means we are go for update
...

Without my friendly goto, I would have to play around with while-loops and flags (TMTOWTDI I guess, even in C sometimes), and the code would have been less readable. The use of goto highlights the fact that it's a tight, local loop, potentially infinite, but we jump back and forth depending on the user's response. If we get input we don't understand, we ask again. If the user wants to edit again, we jump back to the edit call. The circular operation of the prompt is echoed in the code. "Don't set the flag, set the data." Even though there are other ways to do this, getting uppity about goto-type constructs being somehow "impure" is pretty silly these days IMO.

The above is far from tight. Hint: perldoc -f redo.


Apple's sloppy editing that led to their http://gotofail.com/ bug indicates an issue with gotos: With a jump, there's not much the compiler can tell about your intended structure, so it's up to you to catch typos. (Surprised there was not a warning about unreachable code, though. Perhaps gotos make this harder to detect?)

short-circuit operators to avoid cumbersome flag testing: In C and Java and Javascript (and many others) the logical && and || operators will not evaluate the second operand if truth or falseness can be determined from the first operator. So, these provide a clean idiom for repeated flag tests without the indenting mess of multiple ifs.

If "err" is a variable that's zero in the normal case, and set to a non-zero code to indicate a fault, then test a series of steps that set "err" with lines like:

err = do-first-step();
(! err) && (err = do-next-step());
(! err) && (err = do-third-step());
(! err) && (err = do-another-step());
The idiom is "Not error, and so contine processing." If error gets set to non-zero at any point, no further steps are done. The lines don't nest, so in case of failure, err may be tested redundant times, once per remaining step. Often the extra clarity and benefit of not needing to balance all those brackets is worth a few extra tests, especially if the usual case happens more frequently than the error case. (In a kernel goto might be preferable to these extra tests.) This idiom also makes it easy to add or re-order lines to the sequence.

Apple's source code with their extra goto bug is excerpted here: http://www.imperialviolet.org/2014/02/22/applebug.html

Below is a rewrite of this failed code using the "(! err) &&" idiom rather than "if ( err = ... ) goto"(ellipses [...] are where imperialviolet skipped code from the original Apple source.)

  static OSStatus
  SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams,
uint8_t *signature, UInt16 signatureLen)
  {
OSStatuserr;
[...]

err = SSLHashSHA1.update(&hashCtx, &serverRandom); (! err) && (err = SSLHashSHA1.update(&hashCtx, &signedParams); (! err) && (err = SSLHashSHA1.final(&hashCtx, &hashOut));

if ( ! err ) { [...]/* do other stuff only when that final hash succeeded */ }

SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err; }


The StoryOfMel is probably the ultimate story of Goto-based programming, including a snipe about salesmen-vs-programmers.


See also: GoHere, ComeFrom, GotoConsideredHarmful


CategoryCodingConventions, CategoryBranchingAndFlow


EditText of this page (last edited February 25, 2014) or FindPage with title or text search