IT PAPER DEEP-READ · PAPER 37
Edsger W. Dijkstra · Communications of the ACM · 1968
In 1968, the Dutch computer scientist Edsger Dijkstra wrote a two-page letter to an academic journal, titled Go To Statement Considered Harmful. It contained no algorithm and no formula, yet it became one of the most famous pieces of writing in software history and rewrote how we think about "how code should be written." The if / while / for you write today — and the goto that nearly every language now urges you to avoid or has removed entirely — trace back to this letter.
Early programs looked like a list of numbered lines, and goto was a command: "stop reading down the page — jump straight to line 87 and continue there." It could jump forward, jump back, jump into or out of anything. Convenient, genuinely. But stuff a sizeable program full of these jumps and reading it feels like untangling a knotted pair of earbuds — the trade name is "spaghetti code."
He pointed out something delicate: we read code top to bottom, line by line (static text), but a program actually runs step by step through time (a dynamic process). Whoever writes the program must constantly line up those two things — "this line I'm reading corresponds to this step of the run." And he had an observation about people: humans are naturally good at grasping static arrangements, but rather poor at picturing a process that unfolds over time. So the key to good code is to make the static text as much like a map of the dynamic execution as possible.
goto is exactly what rips that map apart. Here's an analogy: reading an ordinary book, a single bookmark tells you where you are. But if every page said "now jump to page such-and-such," bouncing around, the bookmark loses its meaning — from the bookmark alone you couldn't say how far the story has gotten or what happened before.
Dijkstra's claim: using only three "non-jumping" building blocks — go straight down (sequence), pick one of two (an if branch), and repeat (a loop) — is enough to write any program; and code written that way always admits a crisp bookmark of the form "which line I've reached + (if inside a loop) how many times around." The text becomes a reliable map again.
The letter ignited the "structured programming" movement. New languages made if/while/for first-class citizens and pushed goto to the margins; "code should be readable by a human" was, for the first time, placed on equal footing with "it runs." You almost never see goto in serious code today, largely thanks to this letter. One honest caveat: Knuth and others later noted that in a few cases (say, bailing out of several nested loops at once on an error) a single jump reads more clearly — so the mainstream stance is "use it very sparingly," not "ban it outright."
Code is static text; execution is a dynamic process; the human mind is good at the former and poor at the latter. goto can jump anywhere, so "where you're reading" no longer matches "where the run is" — the text stops being a map. Switch to sequence / branch / loop and you can always pin the program's current position with a clear bookmark — so the code becomes readable, checkable, trustworthy.
Want the precise "progress-coordinate" argument, a control-flow comparison diagram, and the later debate? → switch to the Deep version
In this two-page letter, Dijkstra argues that goto (unrestricted jumping) badly decouples a program's static text from the dynamic process it executes, making it impossible to describe "where the program is now and what it has been through" with a small set of meaningful "coordinates"; but if control flow is confined to sequence, selection (if), and iteration (loop), those coordinates always exist — so the code becomes readable, reasoned-about, and verifiable. The letter ignited the structured-programming movement and shaped modern control structures.
if-then-else, selection), repeat a block (while/for, iteration/loop).The author, Edsger W. Dijkstra (Netherlands; 1972 Turing Award), published this in the March 1968 Communications of the ACM — it is in fact a "letter to the editor." Dijkstra's own title was A Case against the GO TO Statement; editor Niklaus Wirth changed it to the punchier Go To Statement Considered Harmful. It builds on the 1966 theoretical result of Böhm and Jacopini, and leads into the 1970s structured-programming movement and the book Structured Programming (1972) by Dijkstra, Hoare, and Dahl.
The dominant languages of the 1960s (FORTRAN, assembly, even ALGOL) used goto as the core means of control: a program was a string of numbered statements with goto jumping arbitrarily among them. Fine for small programs — but as a program grows, the jumps weave into a net and the reader can barely reconstruct in their head "how the execution actually goes."
Dijkstra was after a more fundamental question: on what grounds can we believe a program is correct? He offers an observation about people: human intellect is better at grasping static, structural relations, and rather poor at picturing processes that evolve over time. And a program wears two faces — on paper it is static text; running, it is a dynamic process. Writing, reading, and debugging are all acts of mapping between the two. If that mapping is simple and clear, we keep hold of it; if it is a mess, we lose control. goto is precisely what makes the two lose their grip on each other.
Dijkstra's central argument is not "goto is ugly" but something precise: can we find a small, meaningful set of coordinates for "the program's current progress"? He inspects the structured control flows one by one:
The point: each of these structured control flows lets us derive a set of "progress coordinates" systematically from "where control has reached." And that set of coordinates is exactly the footing on which we talk about program state and write down invariants like "when execution reaches here, X must hold." Without it, correctness reasoning has nowhere to stand.
goto shatters all of this: once arbitrary jumps are allowed, a given textual position can be arrived at from every direction, so "which line you've reached" no longer implies "what happened before," and the textual pointer degenerates into a meaningless coordinate. You can no longer characterize progress compactly, and thus can no longer reason steadily about the code — on paper or in your head. Hence Dijkstra's verdict: goto is "too much an invitation to make a mess of one's program."
Böhm and Jacopini had already proved in 1966 that any computable process can be expressed using only sequence, selection, and iteration — goto is not necessary in expressive power. Dijkstra's proposal follows naturally: give up goto voluntarily and confine programs to these three blocks, in which "progress coordinates always exist." The cost is sometimes an extra boolean variable or a slight detour; the prize is that precious property, "text ≈ map of execution." Note that what he opposes is unrestricted goto, not all jumping — structured branches and loops are, in essence, "tamed jumps."
This is a position paper with no experiments; its "result" is the persuasiveness of the argument itself, plus the theory it invokes: the Böhm–Jacopini theorem guarantees that "deleting goto costs no expressive power," turning "use goto little or not at all" from an aesthetic preference into a grounded engineering claim. Its actionable conclusion is minimal but hard — organize all control flow with sequence / selection / iteration — and it leaves the line still quoted today: "the quality of programmers is a decreasing function of the density of go to statements in the programs they produce." Its influence rests not on numbers but on two decades of industry practice bearing it out.
break / continue / multiple return / exceptions are all "constrained jumps," and abused they can tangle control flow just as badly — the problem was never the goto keyword itself.① In one line: goto decouples static code text from the dynamic execution process; switching to sequence / selection / iteration fixes it — the manifesto of structured programming.
② Insight: the human mind is good at static structure, poor at picturing dynamic processes; good code makes the text a reliable map of execution.
③ Core mechanism: structured control flow always gives "progress" a compact set of coordinates (textual pointer + (loop) count + (call) stack); this is the footing for invariants and correctness reasoning.
④ Harm of goto: arbitrary jumps make a textual position no longer imply "what came before," coordinates degenerate, reasoning loses its ground.
⑤ Theoretical backing: Böhm–Jacopini (1966) proved sequence / selection / iteration can express any process — deleting goto loses no expressive power.
⑥ The famous line: "programmer quality is a decreasing function of goto density"; what he opposes is unrestricted jumping, not all jumping.
⑦ Impact: it ignited structured programming, made if/while/for language standards, and raised readability / provability to first-class criteria.
⑧ Limits: Knuth showed goto is better in a few cases ("use sparingly," not banned); goto is only a scapegoat for unstructured control flow; modern error handling still has legitimate goto.