Introduction: A 55-Year-Old Debate in Modern Go
In 1968, Edsger Dijkstra wrote the now-famous article “Go To Statement Considered Harmful” in the Communications of the ACM.
It was a short but powerful critique of the GOTO
statement, arguing that it leads to unstructured and unreadable "spaghetti code." His ideas shaped modern programming, paving the way for structured programming paradigms that we rely on today.
Fast-forward to today, and we have Go (Golang)—a modern, concise, and efficient language designed for simplicity and performance. And guess what? Go still has goto
.
But should we use it? Does Dijkstra’s argument still apply to a language designed half a century later?
What Was Dijkstra's Problem with GOTO?
Before structured programming, most languages (like Fortran and Assembly) heavily relied on GOTO for control flow. This led to chaotic jumps in execution, making debugging and maintenance a nightmare.
Spaghetti Code in Action
Here’s a simple example of unstructured GOTO
usage in Go:
package main
import "fmt"
func main() {
num := 7
if num%2 == 0 {
goto even
} else {
goto odd
}
even:
fmt.Println("Even number")
return
odd:
fmt.Println("Odd number")
}
🔴 Why is this bad?
- The program jumps unpredictably between labels.
- If the logic becomes more complex, tracking execution flow becomes painful.
- If a bug appears, finding the root cause requires tracing multiple jumps instead of following a clear path.
This is exactly the problem Dijkstra warned us about in 1968
Go’s Take on GOTO
: Discouraged, But Not Forbidden
Go allows goto
, but strongly discourages its use unless absolutely necessary. The official Go documentation states:
"
goto
jumps to a labeled statement and should be used sparingly. It can simplify error handling but often leads to unstructured code."
Unlike Java, Python, and Rust, which completely disallow GOTO
, Go keeps it for specific cases—mainly for breaking deeply nested loops or reducing redundant error handling code.
When Can GOTO
Be Useful in Go?
✅ Breaking Out of Nested Loops (A Rare Exception)
Imagine you have a deeply nested loop structure, and you want to exit immediately once a condition is met. Using goto
can simplify this:
package main
import "fmt"
func main() {
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if i*j > 4 {
goto exitLoop // Break out of both loops
}
fmt.Println(i, j)
}
}
exitLoop:
fmt.Println("Exited the loop")
}
🔹 Why is this acceptable?
- Without
goto
, you might need extra flags or complex if conditions. -
goto
allows immediate escape without unnecessary logic.
Still, this should be used sparingly, as Go provides better alternatives.
Structured Programming in Go: What to Use Instead of GOTO
Go is designed with structured programming in mind, offering better alternatives to goto
.
✅ 1. Using break
with Labels (Cleaner Than goto
)
Instead of goto
, Go allows labeled break statements, which are cleaner and more structured:
package main
import "fmt"
func main() {
outer:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if i*j > 4 {
break outer // Exits both loops cleanly
}
fmt.Println(i, j)
}
}
fmt.Println("Exited the loop")
}
✅ Why is this better?
- More readable than goto.
- The label (
outer
) makes it clear which loop is being exited.
✅ 2. Handling Errors Without GOTO
A common argument for goto
is reducing repeated error-handling code. But Go already has defer and error handling patterns to simplify this.
package main
import (
"errors"
"fmt"
)
func doSomething() error {
return errors.New("Something went wrong")
}
func main() {
if err := doSomething(); err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Success")
}
✅ Why is this better?
- Error handling remains structured.
- No unnecessary jumps—errors are handled where they occur.
Did Dijkstra Win? (Go’s Balance Between Old and New)
Dijkstra’s 1968 paper revolutionized programming, leading to structured programming and the decline of goto
. But Go did not completely remove goto
—instead, it keeps it for rare, justified cases.
So, did Dijkstra win? Yes, mostly.
- Almost all modern programming follows structured programming.
-
goto
is considered harmful unless used in very specific cases. - Even in Go, structured constructs are always preferred over
goto
.
Dijkstra’s Influence on Go
Final Thoughts: Should You Use GOTO
in Go?
❌ No, unless absolutely necessary.
✅ Yes, but only in very specific cases like breaking nested loops.
If you're considering using goto in Go, ask yourself:
- Can I use
break
,return
, ordefer
instead? - Will this make debugging harder in the future?
- Would Dijkstra approve? (Spoiler: Probably not.)
Go is a modern language, and Dijkstra’s insights from 1968 still hold true today. The best Go code follows structured programming principles, making it readable, maintainable, and scalable.
So, next time you're tempted to use goto
, just remember: Dijkstra is watching.
References
Dijkstra, E. W. (1968). Go To Statement Considered Harmful. Communications of the ACM, 11(3), 147-148
Golang Official Documentation: https://golang.org/
Top comments (0)