The goto Statement
In this page:
goto Label
// ...
Label:
// statements
Basic goto Usage
A goto statement transfers control to a label elsewhere in the same function. The label is just an identifier followed by a colon, placed before the statement you want to jump to.
Example: Basic goto Usage
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// main is where the program starts running
func main() {
// Short declaration: create i and infer the type
i := 0
Loop:
if i < 3 {
// Print the values followed by a newline
fmt.Println("i =", i)
i++
goto Loop
}
// Print the values followed by a newline
fmt.Println("done")
}
Login to try C/C++/Java/PHP code in the editor
Restrictions on goto
Go's compiler forbids a goto from jumping into the middle of a block or past a variable declaration it hasn't executed yet, which prevents many of the classic bugs and undefined states that made goto notorious in older languages like C.
Example: Restrictions on goto
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// main is where the program starts running
func main() {
// Short declaration: create n and infer the type
n := 5
// Check whether n > 0
if n > 0 {
goto Positive
}
// Print the values followed by a newline
fmt.Println("non-positive")
return
Positive:
fmt.Println("n is positive:", n)
}
Login to try C/C++/Java/PHP code in the editor
Breaking Out of Nested Loops
One of the few places goto still appears in real Go code is jumping straight out of deeply nested loops when a labeled break would be awkward, though labeled break/continue (covered separately) is generally preferred.
Example: Breaking Out of Nested Loops
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// main is where the program starts running
func main() {
// Loop: repeat while the condition holds
for i := 0; i < 3; i++ {
// Loop: repeat while the condition holds
for j := 0; j < 3; j++ {
// Check whether i == 1 && j == 1
if i == 1 && j == 1 {
goto Done
}
// Print the values followed by a newline
fmt.Println(i, j)
}
}
Done:
fmt.Println("exited nested loops")
}
Login to try C/C++/Java/PHP code in the editor
- Overusing goto to build complex control flow that would be far clearer as a loop or function, creating hard-to-follow 'spaghetti code'.
- Trying to jump into the middle of a block or over a variable declaration, which Go's compiler explicitly forbids.
- Using goto to simulate a loop when a plain for loop (or break/continue with a label) already does the job more idiomatically.
- 'goto label' jumps execution directly to a labeled statement in the same function.
- Go restricts goto so it cannot jump into a block or skip over a variable declaration, preventing many classic goto bugs.
- goto is rarely used in idiomatic Go, mostly reserved for breaking out of deeply nested loops or generated code.
- Labeled break/continue usually solve the same problem more clearly than goto.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: