<p>Goto is often &quot;considered harmful&quot;. But are there good reasons to have goto? If not, what are some of the cons associated with it that imply it should be avoided?</p>

<language-design><control-flow>
What are the pros and cons of goto?
CC BY-SA 4.0
2023-05-18T20:21:37.403Z
Related: https://stackoverflow.com/questions/245742/examples-of-good-gotos-in-c-or-c
naffetS
CC BY-SA 4.0
2023-05-18T21:28:49.227Z
It's notable that the harmful paper was referring to goto between functions, as is native in assembly. The version in C and derivatives is restricted to within one function and therefore drastically less expressive / hazardous, the conclusion from the assembly properties does not necessarily apply.
Jon Chesterfield
CC BY-SA 4.0
2023-05-19T22:34:02.897Z
Pro: It can be convenient sometimes. Con: You get mauled by raptors.
user
CC BY-SA 4.0
2023-07-19T22:31:52.583Z
I always felt that "goto" was unfairly singled out as bad as I have knowledge of assembly.  But most moder code-reviewers wouldn't want it, and their justifications usually make sense.
JosephDoggie
CC BY-SA 4.0
2024-01-10T03:11:57.440Z
A fun challenge for C# programmers: can you write a program with a goto where the goto statement is reachable but the corresponding label is not?  There are a lot of weird cases you have to consider when designing a modern language with a feature as low-level as goto.
Eric Lippert
<p>There is one significant advantage of <code>goto</code> that was not yet mentioned. If your language can be potentially a target for compilation, or if it has powerful metaprogramming capabilities (which, in turn, implies that it's a target for compilation), not having <code>goto</code> makes it much harder to compile a wider class of languages into it, and denying a wide range of optimisations on higher level of translation.</p>
<p>The difference between having and not having <code>goto</code> is in the ability to express irreducible control flow. If for whatever reason your compiler generate an irreducible CFG at the end, you'll have to then do a lot of very inefficient and damaging trasnformations to get out of it - see WebAssembly compiler backends (and some OpenCL implementations) for example of such calamity.</p>

CC BY-SA 4.0
2023-06-30T08:56:41.130Z
2023-06-30T08:56:41.130Z
SK-logic
CC BY-SA 4.0
2023-07-14T15:04:51.763Z
Many people who favor adding runtime constraints to C for the purposes of facilitating optimizations ignore the fact that it undermines the language's usefulness as a back-end for any language that would let programmers do things not provided for by such constraints.
supercat
CC BY-SA 4.0
2023-12-15T23:04:26.793Z
That may (or may not) be an argument for C; but most other languages _aren't_ the target of other compilers, are they?  (Are the needs of human-writable programming languages necessarily sufficiently similar to those of compiler-targeted intermediate languages that it's worth compromising one or the other to squeeze them into the same language?)
gidds
CC BY-SA 4.0
2023-12-15T23:17:26.190Z
@gidds any meta-language (any language with procedural macros) is a target of compilation, for any macro is a compiler. And even if your language is handicapped and does not have macros, you still may need to use external preprocessors (things such as flex and yacc, for example).
SK-logic
CC BY-SA 4.0
2023-12-20T20:14:12.357Z
@gidds: The historical popularity of C as a back-end langauge isn't a result of C being well designed for the purpose, but rather the lack of anything better.  If someone were developing a back-end language, it would be useful for it to recognize different optimization implications of constructs using `goto` versus structured looping constructs, such as allowing some operations to be hoisted ahead of a structured loop without regard for whether that would affect program behavior, but not allowing such latitude with structures using `goto`.
supercat
<h1>Exiting from nested loops</h1>
<p>If your language doesn't allow labeling loops and then doing <code>break label;</code>, <code>goto</code> also works for this:</p>
<pre><code>for ...
  for ...
    if ...
      goto a

a:
  ...
</code></pre>
<p>This is a common pattern in C.</p>

CC BY-SA 4.0
2023-05-18T20:17:27.047Z
2023-05-18T20:17:27.047Z
naffetS
CC BY-SA 4.0
2023-12-21T21:02:41.470Z
What languages support loop labels?
Someone
CC BY-SA 4.0
2023-12-24T12:08:34.797Z
Isn't this a better argument for including loop labels, or multi-level breaks, than it is for including goto?
Jack Aidley
<p>Implementing <code>goto</code> is easy for compiler writers because it neatly maps to assembly language: Unconditional <code>goto</code> is a “jump” instruction, and <code>if</code>...<code>goto</code> is a “branch” instruction.</p>
<p>The reason that <code>goto</code> got such a bad rap is that in early programming languages, it was pretty much the <em>only</em> control-flow statement you had.</p>
<p>For example, if you don't have <code>do</code>...<code>while</code> loops, you emulate them with <code>if</code>...<code>goto</code>.</p>
<pre><code>START_LOOP:
    // do lots of stuff
    if (condition) goto START_LOOP;
</code></pre>
<p>If you don't have block statements (like C's <code>{</code>...<code>}</code> or Pascal's <code>begin</code>...<code>end</code>), then here's how you handle an <code>if</code>...<code>else</code> block:</p>
<pre><code>    if (not condition) goto ELSE;
    // stuff to do if condition is true
    goto END_IF;
ELSE:
    // stuff to do if condition is false
END_IF:
</code></pre>
<p>Do this enough, and your program becomes a “spaghetti code” mess of <code>goto</code> statements.  This complaint was frequently voiced circa 1980, when line-numbered <a href="https://en.wikipedia.org/wiki/BASIC" rel="noreferrer">BASIC</a> was the <em>lingua franca</em> of home computers (Apple II, Commodore, Atari, etc.).  If you've never worked with BASIC, I recommend that you go find some vintage BASIC game, study its code, and convert it to your modern language of choice.  <em>Then</em> you will understand the anti-<code>goto</code> movement.</p>
<p>The point of “structured programming” wasn't really to get rid of <code>goto</code>.  It's still there behind the scenes, in the machine code generated by your compiler.  Rather, it's that by replacing each <code>goto</code> with a more specific keyword — the block <code>if</code>...<code>else</code> statement; the <code>do</code>, <code>while</code>, or <code>for</code> loop; the early-exit <code>break</code>, <code>continue</code>, or <code>return</code>; and the <code>throw</code> and <code>catch</code> (and sometimes <code>finally</code>) for exceptions — the intent of the code becomes more clear.  And you stop <em>thinking</em> in terms of assembly-style “jumps” and “branches”, replacing them with the higher-level constructs of “blocks”, “loops”, and “functions”.</p>
<p>There are still occasions where a <code>goto</code> is convenient.  Like exiting from nested loops (but the loop can be refactored into a function with an early <code>return</code>).  Or <code>goto ERROR;</code> to handle error reporting and cleanup (but this can be replaced with exception handling).</p>
<p>But in modern languages, a <code>goto</code> is never <em>necessary</em>, and there are popular languages that get along just fine without it, like Python or Java.</p>

CC BY-SA 4.0
2023-06-30T16:06:10.810Z
2023-06-30T16:06:10.810Z
dan04
CC BY-SA 4.0
2023-12-18T21:16:47.797Z
I’ve seen the proof for some language that goto is never necessary by transforming any function and destroying all code flow structure.
gnasher729
CC BY-SA 4.0
2023-12-18T21:28:49.370Z
@gnasher729: It's trivial to turn any combination of looping control structures into a single `while` which brackets a combination of `if` and flag assignment statements, without any reverse branches aside from the `while`, but that doesn't mean the latter form is "better".
supercat
CC BY-SA 4.0
2023-12-18T21:33:29.710Z
@gnasher729: In many cases it may be difficult to optimize code containing `goto` without making overly pessimistic allowances for possible program flows, but optimizing code that jumps through hoops to avoid `goto` would be even worse.
supercat
<p>Two pros:</p>
<ul>
<li><code>goto</code> is more or less the equivalent of a <code>JMP</code> instruction in assembly, so it's definitely easier for the compiler.</li>
<li>Whenever I have two loops, and I want to break out of the innermost one, the only option I have (in Java, C#, JavaScript) is <code>return</code>, and that only works (most of the times) if the loops are the only thing in a method:</li>
</ul>
<pre><code>for (int i = 0; i &lt; maxI; i++) {
    for (int j = 0; j &lt; maxJ; j++) {
        if (match(i, j)) {
             // I'd really like to quit both loops here, but `break` only quits the `j` loop ...
        }
    }
}
</code></pre>
<p>Cons:</p>
<ul>
<li>Yes, the ability to jump to <em>anywhere</em> in the current method or program increases the complexity for humans to comprehend the code. The code above can be improved if the language had something like a <code>break all;</code> instruction; at least that keeps the instruction pointer close to the last instruction, as opposed to an unlimited <code>goto</code>.</li>
</ul>

CC BY-SA 4.0
2023-05-18T20:22:48.467Z
2023-05-18T20:22:48.467Z
Glorfindel
CC BY-SA 4.0
2023-05-18T23:49:57.887Z
If your language permits variables with scopes smaller than "function", a `goto` may considerably more complicated than a `JMP`: you now need to handle whatever happens when variables go out of scope.
Mark
CC BY-SA 4.0
2023-05-19T13:47:08.297Z
Java has labels, you can break out of an outer loop by wrapping it in a label
Seggan
CC BY-SA 4.0
2023-07-02T22:22:53.733Z
> *goto is more or less the equivalent of a JMP instruction in assembly, so it's definitely easier for the compiler.*

Definitely not if you are targetting WebAssembly. WebAssembly has no `jmp`.
FlatAssembler
CC BY-SA 4.0
2023-12-15T15:35:17.440Z
As an alternative to labels (which are a kind of limited-use `goto`) or `break all;`, in PHP both `break` and `continue` take an optional integer to jump out of that number of loops, so this example would simply be `break 2;` On the other hand, [PHP added `goto` in version 5.3](https://www.php.net/goto).
IMSoP
<h1>Cleanup tasks / errors</h1>
<p>If you have a complex function that does tasks that can fail, <code>goto</code> can help. This is more useful in C-like languages, where you might need to deallocate memory or something. Maybe you open a file, do some tasks, and for each task, you need to check if it failed. If it failed, then <code>goto</code> to <code>cleanup</code> to close the file and return an error. Otherwise it would just error and not close the file.</p>
<pre><code>  open(file);

  doA;
  if (doA failed) {
    status = E_DOA;
    goto cleanup;
  }

  doB;
  if (doB failed) {
    status = E_DOB;
    goto cleanup;
  }

  do stuff to file;

cleanup:

  close(file);

  return status;
</code></pre>
<p>(idea from <a href="https://stackoverflow.com/a/245781">https://stackoverflow.com/a/245781</a>)</p>

CC BY-SA 4.0
2023-05-18T20:25:19.250Z
2023-12-20T19:29:26.133Z
2023-12-20T19:29:26.133Z
naffetS
CC BY-SA 4.0
2023-05-19T17:24:35.947Z
The main issue here isn't that you have manual memory management, but rather you don't have other constructs like try/catch that would allow you to do the same thing.
Aman Grewal
CC BY-SA 4.0
2023-07-12T19:54:12.780Z
@AmanGrewal - right.  `goto` is a very good replacement for missing language constructs -- but there are other alternatives that can also achieve similar results that are a little more structured (e.g. various constructs involving first class continuations), but best of all is ensuring you have adequate language constructs for expressing things programmers are likely to want to do.
occipita
CC BY-SA 4.0
2023-07-16T21:08:17.060Z
As a structured way to do this, many languages offer a `defer` keyword.
xigoi
<h2>Pro: supporting <code>goto</code> can make it easier to target your language</h2>
<p>For example:</p>
<ul>
<li><p><a href="https://en.wikipedia.org/wiki/Parser_generator" rel="noreferrer">Parser generators</a> often generate <code>goto</code>s, because the transitions of the produced state machine are natural to express using <code>goto</code>.</p>
</li>
<li><p>Transpilers can generate <code>goto</code>s to simplify translating control flow into your language.</p>
</li>
</ul>
<p>More generally it could make life easier for anyone generating code in your language.</p>

CC BY-SA 4.0
2023-07-02T18:04:16.683Z
2023-07-02T18:04:16.683Z
Eldritch Conundrum
CC BY-SA 4.0
2023-07-02T18:08:52.387Z
Welcome! I think both of these points are already made in [SK-logic's answer](https://langdev.stackexchange.com/a/1786/89).
kaya3
CC BY-SA 4.0
2023-07-02T18:26:16.597Z
Oh no... I missed it, because I was initially searching if someone mentioned parser generators.
Eldritch Conundrum
<p><a href="https://eli.thegreenplace.net/2012/07/12/computed-goto-for-efficient-dispatch-tables" rel="noreferrer">Computed gotos</a> make virtual machines faster at dispatching instructions.</p>
<p>Consider the &quot;normal&quot; way of dispatching via a looped <code>switch</code> statement:</p>
<pre><code>while (true) {
  switch (code[pc++]) {  // dispatch next opcode
    case OP_ADD:
      add();
      break;

    case OP_SUB:
      sub();
      break;

    case OP_MUL:
      mul();
      break;

    case OP_DIV:
      div();
      break;
  }
}
</code></pre>
<p>This iterates over a program counter within the user's bytecode and invokes arithmetic functions based on the observed opcode.</p>
<p>The <code>switch</code> statement is, ultimately, the single point of dispatch for all opcodes. That means that a CPU's branch predictor can't really determine a pattern to the next opcode. Consider that over the past few handled instructions within a user's bytecode, the branch predictor will have seen multiple different opcodes. Thus, the prediction for the next <code>switch</code> target cannot be focused onto a single opcode, which means that there will be no (correct) branch prediction!</p>
<p>Fortunately there is a non-standard extension to C/C++ that some compilers implement. <em>Computed gotos</em> allow programs to reference labels directly:</p>
<pre><code>// opcodes must be in consecutive order for this array to be valid
void* table[] = {&amp;&amp;op_add, &amp;&amp;op_sub, &amp;&amp;op_mul, &amp;&amp;op_div};

// start the first dispatch
goto *table[code[pc++]];

op_add:
  add();
  goto *table[code[pc++]];  // dispatch next opcode

op_sub:
  sub();
  goto *table[code[pc++]];  // dispatch next opcode

op_mul:
  mul();
  goto *table[code[pc++]];  // dispatch next opcode

op_div:
  div();
  goto *table[code[pc++]];  // dispatch next opcode
</code></pre>
<p>Here there are multiple points of dispatch because each opcode handler dispatches to the next opcode in the user's bytecode. If the user's bytecode is part of a tight loop, then the branch predictor will see a pattern of the current opcode based solely on the previous opcode. That means prediction is more focused (the current opcode determines the next opcode), which means there will be a (likely correct) branch prediction!</p>
<p>This technique is sometimes referred to as <a href="https://en.wikipedia.org/wiki/Threaded_code#Indirect_threading" rel="noreferrer">indirect threading</a> (not to be confused with multithreading).</p>
<p>CPython's virtual machine will <a href="https://github.com/python/cpython/blob/main/Python/ceval_macros.h" rel="noreferrer">use computed gotos</a> if possible, noting:</p>
<blockquote>
<p>At the time of this writing, the &quot;threaded code&quot; version is up to 15-20% faster than the normal &quot;switch&quot; version, depending on the compiler and the CPU architecture.</p>
</blockquote>

CC BY-SA 4.0
2023-05-19T01:48:27.040Z
2023-06-30T14:01:23.503Z
2023-06-30T14:01:23.503Z
chrisaycock
CC BY-SA 4.0
2023-05-19T02:08:36.063Z
The reason why this gives a performance improvement is not because "there is only one branch". In fact, the exact opposite is true: *there is a "branch" at the end of every opcode*. This helps a modern CPU's branch predictor, which is a cache indexed by the program counter. If there is one big switch statement, there is only one place to branch *from*, so the predictor never gets a chance to predict.
Pseudonym
CC BY-SA 4.0
2023-05-19T02:32:12.263Z
@Pseudonym There is one branch *per opcode dispatch*.
chrisaycock
CC BY-SA 4.0
2023-05-19T02:50:55.227Z
Most compilers would implement the "big switch statement" with one or two branches at the most, assuming that the set of opcodes is dense: one to check the range and the other through a jump table. The range check would be perfectly predicted almost all the time and therefore cost nothing. So the number of branches per dispatch is essentially the same.
Pseudonym
CC BY-SA 4.0
2023-05-19T03:40:19.490Z
@Pseudonym You are correct. I have amended my answer.
chrisaycock
CC BY-SA 4.0
2023-06-30T09:40:21.313Z
It's an indirect threading in your example. Direct threading would have been replacing your bytecode array with label addresses first (e.g., see how OCaml bytecode interpreter is doing it).
SK-logic
CC BY-SA 4.0
2023-06-30T14:00:38.467Z
I wonder if compilers couldn't get smart about this, and compile a switch-in-a-loop to have multiple points of dispatch in the same way.
kaya3
CC BY-SA 4.0
2023-06-30T14:01:43.563Z
@SK-logic Ah, yes. You are correct.
chrisaycock
CC BY-SA 4.0
2023-06-30T14:13:28.273Z
@kaya3-supportthestrike quite a few compilers do compile switch as a dispatch table. It's still much less efficient (due to an extra level of indirection) than a direct threading (storing the jump addresses instead of bytecode.
SK-logic
CC BY-SA 4.0
2023-06-30T14:20:15.860Z
@SK-logic When the switch statement's cases are a contiguous range of integers starting from 0, or can be mapped into such a range using a [perfect hash function](https://en.wikipedia.org/wiki/Perfect_hash_function), then I don't see the problem. The two snippets of code in this answer are semantically equivalent but the second has better performance, so what I'm asking is whether a compiler could recognise the former and compile it to the latter.
kaya3
CC BY-SA 4.0
2023-06-30T15:21:26.267Z
@kaya3-supportthestrike yes, some C compilers would have translated this to the same code. One caveat though - checking for the values not in table. For an 8-bit or 16-bit opcode making just a big table with values pointing to default: is feasible, for something bigger it's still an extra check and jump before using the table.
SK-logic
CC BY-SA 4.0
2023-12-15T15:44:00.753Z
This answer could be improved by mentioning structured _alternatives_ which exist. In particular, [tail calls](https://blog.reverberate.org/2021/04/21/musttail-efficient-interpreters.html) provide the same performance benefits than computed gotos, while ensuring control-flow is structured.
Matthieu M.
<h2>Pros</h2>
<p>One pro of having GOTO is that jumps are a fundamental building block of computer programming, and the GOTO expresses the unconditional jump. There is also a counterpart concept of the 'line label', which is how the target of a jump is expressed.</p>
<p>Discussion of how jumps work is still important when trying to <em>teach</em> people for the first time how computers and programs really work, and how structured blocks are composed from more basic elements.</p>
<p>Even a very modern language cannot be hurt by having the potential to be useful in the classroom. Or put another way, it cannot be bad that languages which are taught in the classroom because they have the facility to express basic concepts, are also fully useful industrial languages.</p>
<p>A second pro is that there are certain algorithms and programming patterns where the use of GOTO remains either the clearest implementation of that algorithm, or the fastest implementation.</p>
<p>Finite state machines are the main example of this residual area, as the transitions between states can occur in a way that doesn't easily reconcile with the hierarchical nature of structured blocks. The structured solution essentially just implements a small processing loop and a variable that controls the movement from one arbitrary branch inside the loop to another - achieving by boilerplate and contrivance what GOTO achieves directly.</p>
<h2>Cons</h2>
<p>The cons of GOTO really relate to its manner of use rather than its mere existence in the language.</p>
<p>One con is that the use of GOTO can make it difficult for an optimising compiler to analyse and transform the code, because the unstructured jumps can't be easily fitted into patterns which the compiler knows can be optimised in a particular way.</p>
<p>Another con is that it is said to promote the creation of so-called spaghetti code, where too much of the structure of the code becomes latent, or analysing possible paths through the code (and verifying them all as legitimate paths) becomes unreasonably challenging to a programmer.</p>
<h2>History</h2>
<p>It's worth saying that some of the worst offences that GOTO was capable of enabling are nowadays no longer possible anyway.</p>
<p>For reasons of speed and simplicity (in some regards), callable procedures in old languages were not always re-entrant - that is, they could not be called recursively. The memory for local variables was allocated statically. As a by-product, you could jump directly into and out of these procedures.</p>
<p>In modern languages, callable procedures have a more complicated and re-entrant implementation, which means GOTO is not compatible with jumping in and out of a procedure body arbitrarily.</p>
<p>There was also a strong culture amongst programmers many decades ago, of relentlessly optimising performance and memory use, without any regard whatsoever for maintainability (that is, the ability to read code to recover an understanding of it, and the ability to modify a program later without upsetting an unclear set of assumptions and dependencies between parts).</p>
<p>Counselling practitioners to forgo to the use of GOTO was often tacitly a counsel to avoid the most horrific optimisations and to employ (what were at that time...) &quot;high-level&quot; constructs that leave the code in a more maintainable condition, and containing fewer tricks.</p>
<p>Another early objection to block-structured programming - and therefore justifying the continued use of GOTO - was that it wasn't capable of expressing all algorithms. But that was proven absolutely false, albeit sometimes that the alternative to GOTO would be at the cost of some additional memory or slightly reduced performance.</p>

CC BY-SA 4.0
2023-07-15T15:58:42.317Z
2023-12-21T18:28:53.050Z
2023-12-21T18:28:53.050Z
Steve
<p>Some algorithms in scientific or mathematical literature are described including the <code>goto</code> construct, the way</p>
<ul>
<li>1 initialize</li>
<li>2 if abc then go to 5 (skip redundant action or if)</li>
<li>3</li>
<li>4 if cde then go to 7 (break out or error handling)</li>
<li>5</li>
<li>6 if ghi then go to 2 (loop)</li>
<li>7 done</li>
</ul>
<p>The steps are often described in plain human language, or some pseudocode is used that provides <code>goto</code>. It is not our choice, the choice has been made by somebody else who is a mathematician and not a software engineer. A good looking solution is to implement each step as a call to function, keeping this list at high level so easily observable.</p>
<p>When implementing such an algorithm in real language, it having <code>goto</code> allows to stay closer to the original description, providing commented sections of the code that match the sections in the article. Otherwise you need a different code that is more apart from the scientific paper used to write it. That makes more difficult to make the matching changes later if the scientific author publishes improvements, derived work or errata.</p>

CC BY-SA 4.0
2023-06-30T08:48:36.110Z
2023-07-12T17:32:42.183Z
2023-07-12T17:32:42.183Z
Audrius Meškauskas
<p>I'd summarize the answers so far as:</p>
<h3>Cons:</h3>
<p>Jumping <strong>into</strong> the middle of some code is almost always <strong>bad</strong>:</p>
<ul>
<li>It can prevent optimization.</li>
<li>It can make the flow of control non-obvious to those reading it (there's no indication that something might jump into this spot).</li>
<li>It can introduce bugs when someone modifies the code not realizing that something could jump into the middle of it.</li>
<li>It makes debugging more complicated, as there's no easy way of finding all the code that could have executed the goto, much less determining which one did.</li>
</ul>
<h3>Pros:</h3>
<p>Jumping <strong>out of</strong> the middle of some code to the end of a section, where the flow would normally have ended up had the goto not happened, is <strong>good</strong>:</p>
<ul>
<li>It makes it easy to get out of nested loops.</li>
<li>It makes it easy to get to a clean-up and return section.</li>
</ul>
<h3>Example:</h3>
<pre><code>{
    ...
} label:
...
</code></pre>
<p>One should be able to know with confidence that the only way to jump to that label is from within the immediately preceding <code>{...}</code>.</p>

CC BY-SA 4.0
2023-05-19T19:41:06.777Z
2023-05-19T19:41:06.777Z
Ray Butterworth
<p>goto was used in Fortran IV which didn’t even have if / then / else forcing you to use two gotos. This was both awful and unavoidable. So a lot of objections against goto come from this time. In today’s languages, situations where goto is useful are very, very rare, assuming you don’t count “break” and “return” as gotos.</p>
<p>It is getting even more rare with compilers that optimise code that in the past could be made faster with goto: Take</p>
<pre><code>Bool done = false;
While (! done) .., 
</code></pre>
<p>The variable could be removed by using goto in the right places, but today a compiler can do that automatically.</p>
<p>And in C++, goto runs into the problem that you are not allowed to goto around a variable declaration. Like</p>
<pre><code>int I = 0;
If (condition) goto xyz;
int j = 0;
</code></pre>
<p>is not allowed.</p>

CC BY-SA 4.0
2024-01-09T00:34:37.110Z
2024-01-09T00:34:37.110Z
gnasher729
<p>There are famous problems caused by jumping into the middle a block from outside it.</p>
<h2>Unrestricted goto may violate variable scope rules</h2>
<p>This code, in C++, is an error. Your compiler must reject it.</p>
<pre class="lang-cpp prettyprint-override"><code>int main() 
{ 
    if (std::rand() &amp; 1) { 
        goto target; 
    } 
 
    { 
        int x = 42; // Pay attention to this line. 
    target: 
        std::cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; '\n'; 
    } 
}
</code></pre>
<p>This, however, is <em>not</em> an error, but will result in undefined behaviour or implementation-defined behaviour (I can't remember which off the top of my head).</p>
<pre class="lang-cpp prettyprint-override"><code>int main() 
{ 
    if (std::rand() &amp; 1) { 
        goto target; 
    } 
 
    { 
        int x; // The only thing that's different... 
        x = 42; // ...is these two lines. 
    target: 
        std::cout &lt;&lt; &quot;x = &quot; &lt;&lt; x &lt;&lt; '\n'; 
    } 
}
</code></pre>
<p>If you're not a C++ language lawyer, you're probably quite confused right now. You may have thought that the two are semantically identical, but they are not.</p>
<p>In the first, <code>x</code> is <em>initialised</em> at the point where it is declared, and the program tries to jump into the middle of its scope. If that jump is ever taken, <code>x</code> could be either initialised or not initialised, which is an inconsistent state.</p>
<p>In the second, <code>x</code> is <em>not initialised</em> where it is declared. So unlike the first example, <code>x</code> is not in an inconsistent state. This code still has undefined/implementation-defined behaviour, but only because the value of <code>x</code> is read.</p>
<p>In the case of <code>int</code>, the distinction doesn't matter, but it does matter when it comes to objects that have destructors. The first example, if allowed, would mean jumping to a point between where an object is constructed and where it is destroyed, and this would result in an unconstructed object having its destructor executed, which would be a serious bug. But presumably for convenience, for the purpose of this rule C++ doesn't care that it's a built-in type.</p>
<h2>Unrestricted goto may reduce opportunities for optimisation</h2>
<p>Consider this loop:</p>
<pre class="lang-c prettyprint-override"><code>int i = 0;

for (i = 0; i &lt; N; ++i) {
    some_code();
    some_loop_invariant_code();
    some_other_code();
}

some_more_code();
</code></pre>
<p>And let's suppose that the compiler discovers the loop-invariant code and decides that it would be good to move it outside the loop. It can transform it to this:</p>
<pre class="lang-c prettyprint-override"><code>int i = 0;

some_loop_invariant_code();
for (i = 0; i &lt; N; ++i) {
    some_code();
    some_other_code();
}

some_more_code();
</code></pre>
<p>So far, so good. But what about this?</p>
<pre class="lang-c prettyprint-override"><code>int i = 0;
if (some_condition()) {
    goto target;
}

for (i = 0; i &lt; N; ++i) {
    some_code();
target:
    some_loop_invariant_code();
    some_other_code();
}

some_more_code();
</code></pre>
<p><em>Where</em>, precisely, should that code be moved to?</p>
<p>The problem is that the control flow graph is not <em>reducible</em>. Reducibility has <a href="https://www.cs.tufts.edu/%7Enr/cs257/archive/jeff-ullman/reducibility.pdf" rel="nofollow noreferrer">a technical definition</a>, but you can think of it, intuitively, as meaning that every loop has a single header and, therefore, a single place to move loop-invariant code to.</p>
<p>We will assume for the moment that moving <code>some_loop_invariant_code</code> <em>before</em> <code>some_condition</code> is not a valid transformation. So the only solution is to either not perform the optimisation, or duplicate code blocks (which, incidentally, is also what <em>partially</em> redundant code optimisation would do).</p>
<pre class="lang-c prettyprint-override"><code>int i = 0;
if (some_condition()) {
    /* I guess? */
    some_loop_invariant_code();
    goto target;
}

some_loop_invariant_code();
for (i = 0; i &lt; N; ++i) {
    some_code();
target:
    some_other_code();
}

some_more_code();
</code></pre>

CC BY-SA 4.0
2023-05-19T01:07:58.057Z
2023-12-16T11:59:31.233Z
2023-12-16T11:59:31.233Z
Pseudonym
CC BY-SA 4.0
2023-12-14T12:04:31.157Z
The first example (if compiled as C with `printf` instead of `cout`) and the second example are actually completely fine and have no implementation defined or undefined behaviour, because `rand() % 1` always evaluates to 0 and the `goto` branch is never taken :)
chrysante
CC BY-SA 4.0
2023-12-14T22:45:31.567Z
@chrysante That's the thing with random numbers. You can never tell!
Pseudonym
CC BY-SA 4.0
2023-12-14T23:47:52.230Z
Are you being serious? You can tell in this case. I'm just wondering if you write `rand() % 1` deliberately or meant `rand() % 2`?
chrysante
CC BY-SA 4.0
2023-12-15T00:29:51.900Z
Duh! I meant to write `rand() & 1`. Thank you for the code review! I will edit.
Pseudonym
# What are the pros and cons of goto?
Posted by: username_0 on 2023-05-18
Goto is often "considered harmful". But are there good reasons to have goto? If not, what are some of the cons associated with it that imply it should be avoided?
**Tags:** language-design control-flow
> **Comments:**
> **username_1**: Related: https://stackoverflow.com/questions/245742/examples-of-good-gotos-in-c-or-c  
> **username_2**: It's notable that the harmful paper was referring to goto between functions, as is native in assembly. The version in C and derivatives is restricted to within one function and therefore drastically less expressive / hazardous, the conclusion from the assembly properties does not necessarily apply.  
> **username_3**: Pro: It can be convenient sometimes. Con: You get mauled by raptors.  
> **username_4**: I always felt that "goto" was unfairly singled out as bad as I have knowledge of assembly.  But most moder code-reviewers wouldn't want it, and their justifications usually make sense.  
> **username_5**: A fun challenge for C# programmers: can you write a program with a goto where the goto statement is reachable but the corresponding label is not?  There are a lot of weird cases you have to consider when designing a modern language with a feature as low-level as goto.  
---
## 12 answers
### Answer by username_24 on 2023-05-19. Score: 18 | Accepted answer
There are famous problems caused by jumping into the middle a block from outside it.
Unrestricted goto may violate variable scope rules
This code, in C++, is an error. Your compiler must reject it.
int main() 
{ 
    if (std::rand() & 1) { 
        goto target; 
    } 
 
    { 
        int x = 42; // Pay attention to this line. 
    target: 
        std::cout << "x = " << x << '\n'; 
    } 
}

This, however, is not an error, but will result in undefined behaviour or implementation-defined behaviour (I can't remember which off the top of my head).
int main() 
{ 
    if (std::rand() & 1) { 
        goto target; 
    } 
 
    { 
        int x; // The only thing that's different... 
        x = 42; // ...is these two lines. 
    target: 
        std::cout << "x = " << x << '\n'; 
    } 
}

If you're not a C++ language lawyer, you're probably quite confused right now. You may have thought that the two are semantically identical, but they are not.
In the first, x is initialised at the point where it is declared, and the program tries to jump into the middle of its scope. If that jump is ever taken, x could be either initialised or not initialised, which is an inconsistent state.
In the second, x is not initialised where it is declared. So unlike the first example, x is not in an inconsistent state. This code still has undefined/implementation-defined behaviour, but only because the value of x is read.
In the case of int, the distinction doesn't matter, but it does matter when it comes to objects that have destructors. The first example, if allowed, would mean jumping to a point between where an object is constructed and where it is destroyed, and this would result in an unconstructed object having its destructor executed, which would be a serious bug. But presumably for convenience, for the purpose of this rule C++ doesn't care that it's a built-in type.
Unrestricted goto may reduce opportunities for optimisation
Consider this loop:
int i = 0;

for (i = 0; i < N; ++i) {
    some_code();
    some_loop_invariant_code();
    some_other_code();
}

some_more_code();

And let's suppose that the compiler discovers the loop-invariant code and decides that it would be good to move it outside the loop. It can transform it to this:
int i = 0;

some_loop_invariant_code();
for (i = 0; i < N; ++i) {
    some_code();
    some_other_code();
}

some_more_code();

So far, so good. But what about this?
int i = 0;
if (some_condition()) {
    goto target;
}

for (i = 0; i < N; ++i) {
    some_code();
target:
    some_loop_invariant_code();
    some_other_code();
}

some_more_code();

Where, precisely, should that code be moved to?
The problem is that the control flow graph is not reducible. Reducibility has a technical definition, but you can think of it, intuitively, as meaning that every loop has a single header and, therefore, a single place to move loop-invariant code to.
We will assume for the moment that moving some_loop_invariant_code before some_condition is not a valid transformation. So the only solution is to either not perform the optimisation, or duplicate code blocks (which, incidentally, is also what partially redundant code optimisation would do).
int i = 0;
if (some_condition()) {
    /* I guess? */
    some_loop_invariant_code();
    goto target;
}

some_loop_invariant_code();
for (i = 0; i < N; ++i) {
    some_code();
target:
    some_other_code();
}

some_more_code();
> **Comments:**
> **username_29** (2023-12-14): The first example (if compiled as C with `printf` instead of `cout`) and the second example are actually completely fine and have no implementation defined or undefined behaviour, because `rand() % 1` always evaluates to 0 and the `goto` branch is never taken :)  
> **username_24** (2023-12-14): @chrysante That's the thing with random numbers. You can never tell!  
> **username_29** (2023-12-14): Are you being serious? You can tell in this case. I'm just wondering if you write `rand() % 1` deliberately or meant `rand() % 2`?  
> **username_24** (2023-12-15): Duh! I meant to write `rand() & 1`. Thank you for the code review! I will edit.  
---
### Answer by username_6 on 2023-06-30. Score: 13
There is one significant advantage of `goto` that was not yet mentioned. If your language can be potentially a target for compilation, or if it has powerful metaprogramming capabilities (which, in turn, implies that it's a target for compilation), not having `goto` makes it much harder to compile a wider class of languages into it, and denying a wide range of optimisations on higher level of translation.

The difference between having and not having `goto` is in the ability to express irreducible control flow. If for whatever reason your compiler generate an irreducible CFG at the end, you'll have to then do a lot of very inefficient and damaging trasnformations to get out of it - see WebAssembly compiler backends (and some OpenCL implementations) for example of such calamity.
> **Comments:**
> **username_7** (2023-07-14): Many people who favor adding runtime constraints to C for the purposes of facilitating optimizations ignore the fact that it undermines the language's usefulness as a back-end for any language that would let programmers do things not provided for by such constraints.  
> **username_8** (2023-12-15): That may (or may not) be an argument for C; but most other languages _aren't_ the target of other compilers, are they?  (Are the needs of human-writable programming languages necessarily sufficiently similar to those of compiler-targeted intermediate languages that it's worth compromising one or the other to squeeze them into the same language?)  
> **username_6** (2023-12-15): @gidds any meta-language (any language with procedural macros) is a target of compilation, for any macro is a compiler. And even if your language is handicapped and does not have macros, you still may need to use external preprocessors (things such as flex and yacc, for example).  
> **username_7** (2023-12-20): @gidds: The historical popularity of C as a back-end langauge isn't a result of C being well designed for the purpose, but rather the lack of anything better.  If someone were developing a back-end language, it would be useful for it to recognize different optimization implications of constructs using `goto` versus structured looping constructs, such as allowing some operations to be hoisted ahead of a structured loop without regard for whether that would affect program behavior, but not allowing such latitude with structures using `goto`.  
---
### Answer by username_1 on 2023-05-18. Score: 12
Exiting from nested loops
If your language doesn't allow labeling loops and then doing break label;, goto also works for this:
for ...
  for ...
    if ...
      goto a

a:
  ...

This is a common pattern in C.
> **Comments:**
> **username_9** (2023-12-21): What languages support loop labels?  
> **username_10** (2023-12-24): Isn't this a better argument for including loop labels, or multi-level breaks, than it is for including goto?  
---
### Answer by username_11 on 2023-06-30. Score: 11
Implementing goto is easy for compiler writers because it neatly maps to assembly language: Unconditional goto is a “jump” instruction, and if...goto is a “branch” instruction.
The reason that goto got such a bad rap is that in early programming languages, it was pretty much the only control-flow statement you had.
For example, if you don't have do...while loops, you emulate them with if...goto.
START_LOOP:
    // do lots of stuff
    if (condition) goto START_LOOP;

If you don't have block statements (like C's {...} or Pascal's begin...end), then here's how you handle an if...else block:
    if (not condition) goto ELSE;
    // stuff to do if condition is true
    goto END_IF;
ELSE:
    // stuff to do if condition is false
END_IF:

Do this enough, and your program becomes a “spaghetti code” mess of goto statements.  This complaint was frequently voiced circa 1980, when line-numbered BASIC was the lingua franca of home computers (Apple II, Commodore, Atari, etc.).  If you've never worked with BASIC, I recommend that you go find some vintage BASIC game, study its code, and convert it to your modern language of choice.  Then you will understand the anti-goto movement.
The point of “structured programming” wasn't really to get rid of goto.  It's still there behind the scenes, in the machine code generated by your compiler.  Rather, it's that by replacing each goto with a more specific keyword — the block if...else statement; the do, while, or for loop; the early-exit break, continue, or return; and the throw and catch (and sometimes finally) for exceptions — the intent of the code becomes more clear.  And you stop thinking in terms of assembly-style “jumps” and “branches”, replacing them with the higher-level constructs of “blocks”, “loops”, and “functions”.
There are still occasions where a goto is convenient.  Like exiting from nested loops (but the loop can be refactored into a function with an early return).  Or goto ERROR; to handle error reporting and cleanup (but this can be replaced with exception handling).
But in modern languages, a goto is never necessary, and there are popular languages that get along just fine without it, like Python or Java.
> **Comments:**
> **username_12** (2023-12-18): I’ve seen the proof for some language that goto is never necessary by transforming any function and destroying all code flow structure.  
> **username_7** (2023-12-18): @gnasher729: It's trivial to turn any combination of looping control structures into a single `while` which brackets a combination of `if` and flag assignment statements, without any reverse branches aside from the `while`, but that doesn't mean the latter form is "better".  
> **username_7** (2023-12-18): @gnasher729: In many cases it may be difficult to optimize code containing `goto` without making overly pessimistic allowances for possible program flows, but optimizing code that jumps through hoops to avoid `goto` would be even worse.  
---
### Answer by username_1 on 2023-05-18. Score: 7
Cleanup tasks / errors
If you have a complex function that does tasks that can fail, goto can help. This is more useful in C-like languages, where you might need to deallocate memory or something. Maybe you open a file, do some tasks, and for each task, you need to check if it failed. If it failed, then goto to cleanup to close the file and return an error. Otherwise it would just error and not close the file.
  open(file);

  doA;
  if (doA failed) {
    status = E_DOA;
    goto cleanup;
  }

  doB;
  if (doB failed) {
    status = E_DOB;
    goto cleanup;
  }

  do stuff to file;

cleanup:

  close(file);

  return status;

(idea from https://stackoverflow.com/a/245781)
> **Comments:**
> **username_18** (2023-05-19): The main issue here isn't that you have manual memory management, but rather you don't have other constructs like try/catch that would allow you to do the same thing.  
> **username_19** (2023-07-12): @AmanGrewal - right.  `goto` is a very good replacement for missing language constructs -- but there are other alternatives that can also achieve similar results that are a little more structured (e.g. various constructs involving first class continuations), but best of all is ensuring you have adequate language constructs for expressing things programmers are likely to want to do.  
> **username_20** (2023-07-16): As a structured way to do this, many languages offer a `defer` keyword.  
---
### Answer by username_21 on 2023-07-02. Score: 7
## Pro: supporting `goto` can make it easier to target your language

For example:

* [Parser generators](https://en.wikipedia.org/wiki/Parser_generator) often generate `goto`s, because the transitions of the produced state machine are natural to express using `goto`.
* Transpilers can generate `goto`s to simplify translating control flow into your language.

More generally it could make life easier for anyone generating code in your language.
> **Comments:**
> **username_22** (2023-07-02): Welcome! I think both of these points are already made in [SK-logic's answer](https://langdev.stackexchange.com/a/1786/89).  
> **username_21** (2023-07-02): Oh no... I missed it, because I was initially searching if someone mentioned parser generators.  
---
### Answer by username_23 on 2023-05-19. Score: 7
Computed gotos make virtual machines faster at dispatching instructions.
Consider the "normal" way of dispatching via a looped switch statement:
while (true) {
  switch (code[pc++]) {  // dispatch next opcode
    case OP_ADD:
      add();
      break;

    case OP_SUB:
      sub();
      break;

    case OP_MUL:
      mul();
      break;

    case OP_DIV:
      div();
      break;
  }
}

This iterates over a program counter within the user's bytecode and invokes arithmetic functions based on the observed opcode.
The switch statement is, ultimately, the single point of dispatch for all opcodes. That means that a CPU's branch predictor can't really determine a pattern to the next opcode. Consider that over the past few handled instructions within a user's bytecode, the branch predictor will have seen multiple different opcodes. Thus, the prediction for the next switch target cannot be focused onto a single opcode, which means that there will be no (correct) branch prediction!
Fortunately there is a non-standard extension to C/C++ that some compilers implement. Computed gotos allow programs to reference labels directly:
// opcodes must be in consecutive order for this array to be valid
void* table[] = {&&op_add, &&op_sub, &&op_mul, &&op_div};

// start the first dispatch
goto *table[code[pc++]];

op_add:
  add();
  goto *table[code[pc++]];  // dispatch next opcode

op_sub:
  sub();
  goto *table[code[pc++]];  // dispatch next opcode

op_mul:
  mul();
  goto *table[code[pc++]];  // dispatch next opcode

op_div:
  div();
  goto *table[code[pc++]];  // dispatch next opcode

Here there are multiple points of dispatch because each opcode handler dispatches to the next opcode in the user's bytecode. If the user's bytecode is part of a tight loop, then the branch predictor will see a pattern of the current opcode based solely on the previous opcode. That means prediction is more focused (the current opcode determines the next opcode), which means there will be a (likely correct) branch prediction!
This technique is sometimes referred to as indirect threading (not to be confused with multithreading).
CPython's virtual machine will use computed gotos if possible, noting:

At the time of this writing, the "threaded code" version is up to 15-20% faster than the normal "switch" version, depending on the compiler and the CPU architecture.
> **Comments:**
> **username_24** (2023-05-19): The reason why this gives a performance improvement is not because "there is only one branch". In fact, the exact opposite is true: *there is a "branch" at the end of every opcode*. This helps a modern CPU's branch predictor, which is a cache indexed by the program counter. If there is one big switch statement, there is only one place to branch *from*, so the predictor never gets a chance to predict.  
> **username_23** (2023-05-19): @Pseudonym There is one branch *per opcode dispatch*.  
> **username_24** (2023-05-19): Most compilers would implement the "big switch statement" with one or two branches at the most, assuming that the set of opcodes is dense: one to check the range and the other through a jump table. The range check would be perfectly predicted almost all the time and therefore cost nothing. So the number of branches per dispatch is essentially the same.  
> **username_23** (2023-05-19): @Pseudonym You are correct. I have amended my answer.  
> **username_6** (2023-06-30): It's an indirect threading in your example. Direct threading would have been replacing your bytecode array with label addresses first (e.g., see how OCaml bytecode interpreter is doing it).  
> **username_22** (2023-06-30): I wonder if compilers couldn't get smart about this, and compile a switch-in-a-loop to have multiple points of dispatch in the same way.  
> **username_23** (2023-06-30): @SK-logic Ah, yes. You are correct.  
> **username_6** (2023-06-30): @kaya3-supportthestrike quite a few compilers do compile switch as a dispatch table. It's still much less efficient (due to an extra level of indirection) than a direct threading (storing the jump addresses instead of bytecode.  
> **username_22** (2023-06-30): @SK-logic When the switch statement's cases are a contiguous range of integers starting from 0, or can be mapped into such a range using a [perfect hash function](https://en.wikipedia.org/wiki/Perfect_hash_function), then I don't see the problem. The two snippets of code in this answer are semantically equivalent but the second has better performance, so what I'm asking is whether a compiler could recognise the former and compile it to the latter.  
> **username_6** (2023-06-30): @kaya3-supportthestrike yes, some C compilers would have translated this to the same code. One caveat though - checking for the values not in table. For an 8-bit or 16-bit opcode making just a big table with values pointing to default: is feasible, for something bigger it's still an extra check and jump before using the table.  
> **username_25** (2023-12-15): This answer could be improved by mentioning structured _alternatives_ which exist. In particular, [tail calls](https://blog.reverberate.org/2021/04/21/musttail-efficient-interpreters.html) provide the same performance benefits than computed gotos, while ensuring control-flow is structured.  
---
### Answer by username_13 on 2023-05-18. Score: 6
Two pros:

goto is more or less the equivalent of a JMP instruction in assembly, so it's definitely easier for the compiler.
Whenever I have two loops, and I want to break out of the innermost one, the only option I have (in Java, C#, JavaScript) is return, and that only works (most of the times) if the loops are the only thing in a method:

for (int i = 0; i < maxI; i++) {
    for (int j = 0; j < maxJ; j++) {
        if (match(i, j)) {
             // I'd really like to quit both loops here, but `break` only quits the `j` loop ...
        }
    }
}

Cons:

Yes, the ability to jump to anywhere in the current method or program increases the complexity for humans to comprehend the code. The code above can be improved if the language had something like a break all; instruction; at least that keeps the instruction pointer close to the last instruction, as opposed to an unlimited goto.
> **Comments:**
> **username_14** (2023-05-18): If your language permits variables with scopes smaller than "function", a `goto` may considerably more complicated than a `JMP`: you now need to handle whatever happens when variables go out of scope.  
> **username_15** (2023-05-19): Java has labels, you can break out of an outer loop by wrapping it in a label  
> **username_16** (2023-07-02): > *goto is more or less the equivalent of a JMP instruction in assembly, so it's definitely easier for the compiler.*

Definitely not if you are targetting WebAssembly. WebAssembly has no `jmp`.  
> **username_17** (2023-12-15): As an alternative to labels (which are a kind of limited-use `goto`) or `break all;`, in PHP both `break` and `continue` take an optional integer to jump out of that number of loops, so this example would simply be `break 2;` On the other hand, [PHP added `goto` in version 5.3](https://www.php.net/goto).  
---
### Answer by username_26 on 2023-07-15. Score: 3
## Pros

One pro of having GOTO is that jumps are a fundamental building block of computer programming, and the GOTO expresses the unconditional jump. There is also a counterpart concept of the 'line label', which is how the target of a jump is expressed.

Discussion of how jumps work is still important when trying to *teach* people for the first time how computers and programs really work, and how structured blocks are composed from more basic elements.

Even a very modern language cannot be hurt by having the potential to be useful in the classroom. Or put another way, it cannot be bad that languages which are taught in the classroom because they have the facility to express basic concepts, are also fully useful industrial languages.

A second pro is that there are certain algorithms and programming patterns where the use of GOTO remains either the clearest implementation of that algorithm, or the fastest implementation.

Finite state machines are the main example of this residual area, as the transitions between states can occur in a way that doesn't easily reconcile with the hierarchical nature of structured blocks. The structured solution essentially just implements a small processing loop and a variable that controls the movement from one arbitrary branch inside the loop to another - achieving by boilerplate and contrivance what GOTO achieves directly.

## Cons

The cons of GOTO really relate to its manner of use rather than its mere existence in the language.

One con is that the use of GOTO can make it difficult for an optimising compiler to analyse and transform the code, because the unstructured jumps can't be easily fitted into patterns which the compiler knows can be optimised in a particular way.

Another con is that it is said to promote the creation of so-called spaghetti code, where too much of the structure of the code becomes latent, or analysing possible paths through the code (and verifying them all as legitimate paths) becomes unreasonably challenging to a programmer.

## History

It's worth saying that some of the worst offences that GOTO was capable of enabling are nowadays no longer possible anyway.

For reasons of speed and simplicity (in some regards), callable procedures in old languages were not always re-entrant - that is, they could not be called recursively. The memory for local variables was allocated statically. As a by-product, you could jump directly into and out of these procedures.

In modern languages, callable procedures have a more complicated and re-entrant implementation, which means GOTO is not compatible with jumping in and out of a procedure body arbitrarily.

There was also a strong culture amongst programmers many decades ago, of relentlessly optimising performance and memory use, without any regard whatsoever for maintainability (that is, the ability to read code to recover an understanding of it, and the ability to modify a program later without upsetting an unclear set of assumptions and dependencies between parts).

Counselling practitioners to forgo to the use of GOTO was often tacitly a counsel to avoid the most horrific optimisations and to employ (what were at that time...) "high-level" constructs that leave the code in a more maintainable condition, and containing fewer tricks.

Another early objection to block-structured programming - and therefore justifying the continued use of GOTO - was that it wasn't capable of expressing all algorithms. But that was proven absolutely false, albeit sometimes that the alternative to GOTO would be at the cost of some additional memory or slightly reduced performance.
---
### Answer by username_27 on 2023-06-30. Score: 2
Some algorithms in scientific or mathematical literature are described including the `goto` construct, the way

* 1 initialize
* 2 if abc then go to 5 (skip redundant action or if)
* 3
* 4 if cde then go to 7 (break out or error handling)
* 5
* 6 if ghi then go to 2 (loop)
* 7 done

The steps are often described in plain human language, or some pseudocode is used that provides `goto`. It is not our choice, the choice has been made by somebody else who is a mathematician and not a software engineer. A good looking solution is to implement each step as a call to function, keeping this list at high level so easily observable.

When implementing such an algorithm in real language, it having `goto` allows to stay closer to the original description, providing commented sections of the code that match the sections in the article. Otherwise you need a different code that is more apart from the scientific paper used to write it. That makes more difficult to make the matching changes later if the scientific author publishes improvements, derived work or errata.
---
### Answer by username_28 on 2023-05-19. Score: 2
I'd summarize the answers so far as:
Cons:
Jumping into the middle of some code is almost always bad:

It can prevent optimization.
It can make the flow of control non-obvious to those reading it (there's no indication that something might jump into this spot).
It can introduce bugs when someone modifies the code not realizing that something could jump into the middle of it.
It makes debugging more complicated, as there's no easy way of finding all the code that could have executed the goto, much less determining which one did.

Pros:
Jumping out of the middle of some code to the end of a section, where the flow would normally have ended up had the goto not happened, is good:

It makes it easy to get out of nested loops.
It makes it easy to get to a clean-up and return section.

Example:
{
    ...
} label:
...

One should be able to know with confidence that the only way to jump to that label is from within the immediately preceding {...}.
---
### Answer by username_12 on 2024-01-09. Score: 0
goto was used in Fortran IV which didn’t even have if / then / else forcing you to use two gotos. This was both awful and unavoidable. So a lot of objections against goto come from this time. In today’s languages, situations where goto is useful are very, very rare, assuming you don’t count “break” and “return” as gotos.
It is getting even more rare with compilers that optimise code that in the past could be made faster with goto: Take
Bool done = false;
While (! done) .., 

The variable could be removed by using goto in the right places, but today a compiler can do that automatically.
And in C++, goto runs into the problem that you are not allowed to goto around a variable declaration. Like
int I = 0;
If (condition) goto xyz;
int j = 0;

is not allowed.
---
