Mea culpa! Sometimes, the experts agree, GOTO can be very useful.
When I wrote a few weeks about Apple's SSL GOTO security fiasco, I put the blame on GOTO. I quoted no less a seer than programming guru Edsger W. Dijkstra who wrote way back in 1968 that the goto statement should be abolished from all "higher level" programming languages.
Since then, I've had it gently drilled into my head by programming experts that are sometimes — okay, many times — using GOTO not only makes perfect sense, sometimes it's the best choice.
For example, SmartBear reader ohengel wrote, "I generally agree that many uses of the goto command are undesirable, but not all are. A good counter-example is the state machine, sometimes also used and known as a syntax machine. It works very well and with unmatched performance when you use goto commands." State machines show when certain Boolean conditions are met.
John Stracke, a software architect for ITA Software agrees with ohengel. Stracke writes, "I hate GOTO, you hate GOTO, all Right-Thinking Modern Programmers hate GOTO. It’s a primitive, archaic construct, left over from machine languages, where primitive constructs make sense. When used, it enables bad coding practices, leads to bizarre bugs, and generally contributes to the decline of civilization. But, there is one case where GOTO is The Right Thing: finite state machines."
Stracke explains, "Think about it. The states of a finite state machine basically correspond to the program counter of a CPU. In this view, state transitions are GOTOs, right? So you can either build your code to store your FSM’s state in some sort of variable (in which case assignments to that variable are GOTOs in disguise), or you can be honest with yourself and write GOTO-based code." Okay, so that's one example, but how often do you use state machines?
Well, it turns out GOTOs are still alive, well, and doing useful work in more than just this one example.
Indeed, GOTOs perform essential work in the Linux kernel. No less a figure than Dirk Hohndel, Intel's Chief Linux and Open Source Technologist, set me straight. He writes, "The Linux kernel is full of GOTOs. So are most other well-maintained C programs. GOTO used in the right circumstances makes for easier-to-read, easier-to-maintain code."
"For example?" I ask.
Hohndel replies, "It's quite simple. If you write a function that tests lots of conditions but needs to clean up when exiting, you can either do this with lots and lots of identical code repeated all over the code, or with nested IF statements that get way too many levels of indentation – or you can have a clearly marked exit point and jump to it."
Of course, you can't use GOTO indiscriminately. Hohndel gave a few simple rules for the correct use of GOTO:
- Only jump forward, never backward.
- Only jump to the end of a block. (It doesn't have to be the end of the function, but usually is.)
- Use good names for the label (e.g. goto error_cleanup;).
- Use it consistently.
For a sample of when it's done right, Hohndel points to When To Use Goto When Programming in C.
As for Apple's fiasco, Hohndel opines, "The problem with Apple's code is a lack of review, not the use of GOTO."
Hohndel's not the only top programmer who sees positive good coming from correct GOTO use. Jeff Law and Jason Merrill, Red Hat engineers and, oh by the way, both members of the GCC (GNU Compiler Collection) steering committee, believe that GOTO can sometimes help with code clarity. In the case of the Apple SSL error, Merrill told Dr. Dobbs, it appears GOTO was used to make the code easier to read. Using GOTO to micro-optimize your code, however, is still a bad idea. "Clarity trumps micro-optimization most of the time," says Merrill.
Last, but by no means least, no less a figure than Linux's creator, Linus Torvalds defended GOTO in the LKML (Linux Kernel Mailing List) back in 2003. Torvalds wrote:
I think GOTOs are fine, and they are often more readable than large amounts of indentation. That's especially true if the code flow isn't actually naturally indented (in this case it is, so I don't think using GOTO is in any way clearer than not, but in general GOTOs can be quite good for readability).
. . .
[S]ometimes structure is bad, and gets into the way, and using a GOTO is just much clearer. For example, it is quite common to have conditionals THAT DO NOT NEST.
In which case you have two possibilities
- use GOTO, and be happy, since it doesn't enforce nesting
This makes the code more readable, since the code just does what the algorithm says it should do.
- duplicate the code, and rewrite it in a nesting form so that you can use the structured jumps.
This often makes the code much less readable, harder to maintain, and bigger.
Okay! I surrender. I'm at best a mediocre programmer, but if Torvalds, other programmers, and three top Linux developers, who work with C every day of the year, agree that GOTO can be extremely useful – who am I to argue?
So, go forth! Use GOTO! Just make darn sure you're using it correctly is all I ask of you.