At the machine code level, a goto is a form of branch or jump statement, in some cases combined with a stack adjustment.
The primary criticism is that code that uses goto statements is harder to understand than alternative constructions.
[5] It did, however, spark a prominent debate among computer scientists, educators, language designers and application programmers that saw a slow but steady shift away from the formerly ubiquitous use of the GOTO.
Probably the most famous criticism of GOTO is a 1968 letter by Edsger Dijkstra called "Go-to statement considered harmful".
[3] In that letter, Dijkstra argued that unrestricted GOTO statements should be abolished from higher-level languages because they complicated the task of analyzing and verifying the correctness of programs (particularly those involving loops).
[9] In The C Programming Language, Brian Kernighan and Dennis Ritchie warn that goto is "infinitely abusable", but also suggest that it could be used for end-of-function error handlers and for multi-level breaks from loops.
[11] Other programmers, including Linux kernel designer and coder Linus Torvalds or software engineer and book author Steve McConnell, also object to Dijkstra's point of view, stating that GOTOs can be a useful language feature, improving program speed, size and code clarity, but only when used in a sensible way by a comparably sensible programmer.
[15][16] According to computer science professor John Regehr, in 2013, there were about 100,000 instances of goto in the Linux kernel code.
[18] For instance, Bertrand Meyer wrote in his 2009 textbook that instructions like break and continue "are just the old goto in sheep's clothing".
The viewpoint that disturbing the control flow in code is undesirable may be seen in the design of some programming languages, for instance Ada[26] visually emphasizes label definitions using angle brackets.
However, a simple, unthinking ban on the goto statement does not necessarily lead immediately to beautiful programming: an unstructured programmer is just as capable of constructing a Byzantine tangle without using any goto's (perhaps substituting oddly-nested loops and Boolean control variables, instead).
Many programmers adopt a moderate stance: goto's are usually to be avoided, but are acceptable in a few well-constrained situations, if necessary: as multi-level break statements, to coalesce common actions inside a switch statement, or to centralize cleanup tasks in a function with several error returns.
[34] However, throwing and catching an exception inside a function can be extraordinarily inefficient in some languages; a prime example is Objective-C, where a goto is a much faster alternative.
[39] This resulted in the ability to structure programs using well-nested executions of routines drawn from a library.
Multi-way branching replaces the "computed goto" in which the instruction to jump to is determined dynamically (conditionally).
[40] In practice, a strict adherence to the basic three-structure template of structured programming yields highly nested code, due to inability to exit a structured unit prematurely, and a combinatorial explosion with quite complex program state data to handle all possible conditions.
In Scheme, a Lisp dialect developed by Steele with Gerald Jay Sussman, tail call optimization is mandatory.
A combination of state variables and structured control, notably an overall switch statement, can allow a subroutine to resume execution at an arbitrary point on subsequent calls, and is a structured alternative to goto statements in the absence of coroutines; this is a common idiom in C, for example.
The Common Lisp GO operator also has this stack unwinding property, despite the construct being lexically scoped, as the label to be jumped to can be referenced from a closure.
One of the main alternatives is message passing, which is of particular importance in concurrent computing, interprocess communication, and object oriented programming.
By encapsulating state data, object-oriented programming reduced software complexity to interactions (messages) between objects.
However, some compilers allowed accidentally treating this variable as an integer thereafter, for example increment it, resulting in unspecified behavior at goto time.
[49] 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).
Up to the 1985 ANSI COBOL standard had the ALTER statement which could be used to change the destination of an existing GO TO, which had to be in a paragraph by itself.
[61][62] However, it does not allow jumping to a label outside of the current scope, and respects object disposal and finally constructs, making it significantly less powerful and dangerous than the goto keyword in other programming languages.
Other languages may have their own separate keywords for explicit fallthroughs, which can be considered a version of goto restricted to this specific purpose.