Lably
Skip to content

Goto

One-way software control-flow statement

  • 19 min read
  • 5 chapters

Related on Lably

Through Computer programming, Control flow and Statement (computer science)

A goto statement is included in a language, primarily, to provide access to the machine code jump instruction (a.k.a. branch or transfer), but due to potential problems with the use of jump semantics, languages have over time been augmented with other flow-control mechanisms intended to replace the need for and use of goto. Many modern languages do not include a goto statement at all. Many languages that do include a goto statement restrict its use in order to limit the problems that its use might incur. Further, as its use is generally considered a poor choice, software developers tend to avoid using it even when using a language that provides it.

In general, use of goto is considered a poor choice as it leads to code with higher cognitive load and more bugs than code that uses more structured flow-control. The use of goto was common in the early days of computing, but via the concerted effort of the structured programming movement in the 1960s and 1970s, that aimed to replace goto with more structured flow-control, its use has declined significantly. Nonetheless, goto is still used today, but generally limited to specific scenarios.

The structured program theorem proved that the goto statement is not necessary to write programs that can be expressed as flow charts; some combination of the three programming constructs of sequence, selection, and iteration are sufficient for any computation that can be performed by a Turing machine, with the caveat that code duplication and additional variables may be required.

Language support

Support of goto varies by language. Languages designed long ago tend to have unrestricted support and newer languages tend to have restricted or no support. For example, C does not permit a jump to a label in a different function.

C# and Visual Basic .NET both support goto. However, they do not allow jumping to a label outside of the containing scope, and respects object disposal and finally constructs, making it significantly less powerful and less dangerous than goto in other languages. They also make case and default keywords labels, whose scope is the enclosing switch statement. goto case or goto default is used as a replacement for implicit fallthrough, which is not allowed.

Many languages lack goto semantics. Java, has a reserved word goto but it is not usable, although compiled .class files generate goto and label statements. Python does not support goto, although there are several joke modules that provide it. PHP did not support goto until version 5.3.

PL/I has a goto statement that unwinds the stack for an out-of-block transfer and does not permit a transfer into a block.

Most languages that have a goto-semantics statement use the keyword goto, but other syntax is used; particularly in older languages. For example, MAD uses TRANSFER TO, and APL uses a right-pointing arrow, →.

Functional programming languages such as Scheme generally do not have goto, instead using continuations.

Computed and assigned

In Fortran, a computed goto jumps to one of several labels in a list, based on the value of an expression. An example is goto (20,30,40) i. The equivalent construct in C is the switch statement, and in newer Fortran a SELECT CASE construct is the recommended syntactical alternative. BASIC had a 'On GoTo' statement that achieved the same goal, but in Visual Basic this construct is no longer supported.

In versions prior to Fortran 95, Fortran also had an assigned goto variant that transfers control to a statement label (line number) which is stored in (assigned to) an integer variable. Jumping to an integer variable that had not been ASSIGNed to was unfortunately possible, and was a major source of bugs involving assigned goto statements. The Fortran assign statement only allows a constant (existing) line number to be assigned to the integer variable. However, some compilers allowed accidentally treating this variable as an integer thereafter, for example increment it, resulting in unspecified behavior at goto time. The following code demonstrates the behavior of the goto i when line i is unspecified:

<span id="mwkg"></span><span class="w" id="mwkw"> </span><span class="k" id="mwlA">assign </span><span class="mi" id="mwlQ">200</span><span class="w" id="mwlg"> </span><span class="n" id="mwlw">to</span><span class="w" id="mwmA"> </span><span class="n" id="mwmQ">i</span> <span class="w" id="mwmg"> </span><span class="n" id="mwmw">i</span><span class="w" id="mwnA"> </span><span class="o" id="mwnQ">=</span><span class="w" id="mwng"> </span><span class="n" id="mwnw">i</span><span class="o" id="mwoA">+</span><span class="mi" id="mwoQ">1</span> <span class="w" id="mwog"> </span><span class="k" id="mwow">goto</span><span class="w" id="mwpA"> </span><span class="n" id="mwpQ">i</span><span class="w" id="mwpg"> </span><span class="c" id="mwpw">! unspecified behavior</span> <span class="mi" id="mwqA">200</span><span class="w" id="mwqQ"> </span><span class="k" id="mwqg">write</span><span class="p" id="mwqw">(</span><span class="o" id="mwrA">*</span><span class="p" id="mwrQ">,</span><span class="o" id="mwrg">*</span><span class="p" id="mwrw">)</span><span class="w" id="mwsA"> </span><span class="s2" id="mwsQ">"this is valid line number"</span>

Several C compilers implement two non-standard C/C++ extensions relating to goto statements originally introduced by gcc. The GNU extension allows the address of a label inside the current function to be obtained as a void* using the unary, prefix label value operator &&. The goto instruction is also extended to allow jumping to an arbitrary void* expression. This C extension is referred to as a computed goto in documentation of the C compilers that support it; its semantics are a superset of Fortran's assigned goto, because it allows arbitrary pointer expressions as the goto target, while Fortran's assigned goto doesn't allow arbitrary expressions as jump target. As with the standard goto in C, the GNU C extension allows the target of the computed goto to reside only in the current function. Attempting to jump outside the current function results in unspecified behavior.

Some variants of BASIC also support a computed goto in the sense used in GNU C, i.e. in which the target can be any line number, not just one from a list. For example, in MTS BASIC one could write GOTO i*1000 to jump to the line numbered 1000 times the value of a variable i (which might represent a selected menu option, for example).

PL/I label variables achieve the effect of the computed or assigned goto.

ALTER

Up to the 1985, ANSI standard COBOL had the ALTER statement which could be used to change the destination of a GO TO, which had to be in a paragraph by itself. The ALTER statement was deemed obsolete in the COBOL 1985 standard and deleted in 2002 (see COBOL self-modifying code). The feature, which allowed polymorphism, was frequently condemned and seldom used.

Perl goto

Perl has a goto statement that takes a function name and transfers control by effectively substituting one function call for another (a tail call). The new function does not return to the goto, but instead to the place from which the original function was called.

Emulated goto

There are several languages that do not directly support goto, but goto emulation provides some goto-like capability, albeit with restrictions. One can emulate goto in Java, JavaScript, and Python.

PL/I label variable

The PL/I data type label can be used to implement both assigned and computed goto, and PL/I allows branching outside of the current block. A procedure can receive a label as an argument which can then exit with a branch. The value of a label variable includes the address of a stack frame, and a goto out of block pops the stack.

The following implements an assigned goto.

<span id="mwAQE"></span><span class="w" id="mwAQI"> </span><span class="n" id="mwAQM">declare</span><span class="w" id="mwAQQ"> </span><span class="n" id="mwAQU">where</span><span class="w" id="mwAQY"> </span><span class="n" id="mwAQc">label</span><span class="p" id="mwAQg">;</span> <span class="w" id="mwAQk"> </span><span class="n" id="mwAQo">where</span><span class="w" id="mwAQs"> </span><span class="o" id="mwAQw">=</span><span class="w" id="mwAQ0"> </span><span class="n" id="mwAQ4">somewhere</span><span class="p" id="mwAQ8">;</span> <span class="w" id="mwARA"> </span><span class="nb" id="mwARE">goto</span><span class="w" id="mwARI"> </span><span class="n" id="mwARM">where</span><span class="p" id="mwARQ">;</span> <span class="w" id="mwARU"> </span><span class="o" id="mwARY">...</span> <span class="n" id="mwARc">somewhere:</span> <span class="w" id="mwARg"> </span><span class="o" id="mwARk">...</span>

The following implements a computed goto.

<span id="mwAR0"></span><span class="w" id="mwAR4"> </span><span class="n" id="mwAR8">declare</span><span class="w" id="mwASA"> </span><span class="n" id="mwASE">where</span><span class="w" id="mwASI"> </span><span class="p" id="mwASM">(</span><span class="mi" id="mwASQ">5</span><span class="p" id="mwASU">)</span><span class="w" id="mwASY"> </span><span class="n" id="mwASc">label</span><span class="p" id="mwASg">;</span> <span class="w" id="mwASk"> </span><span class="n" id="mwASo">declare</span><span class="w" id="mwASs"> </span><span class="n" id="mwASw">inx</span><span class="w" id="mwAS0"> </span><span class="n" id="mwAS4">fixed</span><span class="p" id="mwAS8">;</span> <span class="w" id="mwATA"> </span><span class="n" id="mwATE">where</span><span class="p" id="mwATI">(</span><span class="mi" id="mwATM">1</span><span class="p" id="mwATQ">)</span><span class="w" id="mwATU"> </span><span class="o" id="mwATY">=</span><span class="w" id="mwATc"> </span><span class="n" id="mwATg">abc</span><span class="p" id="mwATk">;</span> <span class="w" id="mwATo"> </span><span class="n" id="mwATs">where</span><span class="p" id="mwATw">(</span><span class="mi" id="mwAT0">2</span><span class="p" id="mwAT4">)</span><span class="w" id="mwAT8"> </span><span class="o" id="mwAUA">=</span><span class="w" id="mwAUE"> </span><span class="n" id="mwAUI">xyz</span><span class="p" id="mwAUM">;</span> <span class="w" id="mwAUQ"> </span><span class="o" id="mwAUU">...</span> <span class="w" id="mwAUY"> </span><span class="nb" id="mwAUc">goto</span><span class="w" id="mwAUg"> </span><span class="n" id="mwAUk">where</span><span class="p" id="mwAUo">(</span><span class="n" id="mwAUs">inx</span><span class="p" id="mwAUw">);</span> <span class="w" id="mwAU0"> </span><span class="o" id="mwAU4">...</span> <span class="w" id="mwAU8"> </span><span class="n" id="mwAVA">abc:</span> <span class="w" id="mwAVE"> </span><span class="o" id="mwAVI">...</span> <span class="w" id="mwAVM"> </span><span class="n" id="mwAVQ">xyz:</span> <span class="w" id="mwAVU"> </span><span class="o" id="mwAVY">...</span>

Another way to get an equivalent result is by using a label constant array which doesn't use a label variable:

<span id="mwAVw"></span><span class="w" id="mwAV0"> </span><span class="n" id="mwAV4">declare</span><span class="w" id="mwAV8"> </span><span class="n" id="mwAWA">inx</span><span class="w" id="mwAWE"> </span><span class="n" id="mwAWI">fixed</span><span class="p" id="mwAWM">;</span> <span class="w" id="mwAWQ"> </span><span class="o" id="mwAWU">...</span> <span class="w" id="mwAWY"> </span><span class="nb" id="mwAWc">goto</span><span class="w" id="mwAWg"> </span><span class="n" id="mwAWk">where</span><span class="p" id="mwAWo">(</span><span class="n" id="mwAWs">inx</span><span class="p" id="mwAWw">);</span> <span class="w" id="mwAW0"> </span><span class="o" id="mwAW4">...</span> <span class="w" id="mwAW8"> </span><span class="n" id="mwAXA">where</span><span class="p" id="mwAXE">(</span><span class="mi" id="mwAXI">1</span><span class="p" id="mwAXM">):</span> <span class="w" id="mwAXQ"> </span><span class="o" id="mwAXU">...</span> <span class="w" id="mwAXY"> </span><span class="n" id="mwAXc">where</span><span class="p" id="mwAXg">(</span><span class="mi" id="mwAXk">2</span><span class="p" id="mwAXo">):</span> <span class="w" id="mwAXs"> </span><span class="o" id="mwAXw">...</span>

Sign in to keep reading

4 more chapters are free with a Lably account.

More in Computing and communication

Source and licence. Adapted from the Wikipedia article “Goto” (this version, 2026-07-17) by its contributors, shared under CC BY-SA 4.0. Lablypedia has left out its tables, references and most pictures, and linked it to other Lablypedia articles.