ZetCode

Golang goto keyword

last modified May 7, 2025

This tutorial explains how to use the goto keyword in Go. We'll cover jump control basics with practical examples of using goto statements.

The goto statement transfers control to a labeled statement within the same function. It provides an unconditional jump to another part of the code.

In Go, goto must jump to a label declared in the same function. It cannot skip variable declarations or jump into other blocks. Use it sparingly.

Basic goto example

The simplest use of goto jumps to a label in the same function. This example demonstrates basic goto functionality.

basic_goto.go
package main

import "fmt"

func main() {
    fmt.Println("Start")
    
    goto skip
    fmt.Println("This won't print")
    
skip:
    fmt.Println("End")
}

The program jumps over the middle print statement directly to the skip label. The goto provides unconditional control transfer.

Goto in a loop

goto can be used to break out of nested loops. This example shows how to exit multiple loops with a single goto statement.

loop_goto.go
package main

import "fmt"

func main() {
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("i=%d, j=%d\n", i, j)
            
            if i == 1 && j == 1 {
                goto exit
            }
        }
    }
    
exit:
    fmt.Println("Exited both loops")
}

When i and j both equal 1, the goto jumps to the exit label. This immediately exits both nested loops without needing complex condition checks.

Error handling with goto

A common use of goto in Go is error handling. This pattern helps centralize cleanup code when errors occur.

error_goto.go
package main

import (
    "fmt"
    "errors"
)

func main() {
    err := process()
    if err != nil {
        fmt.Println("Error:", err)
    }
}

func process() error {
    resource1 := "open resource1"
    fmt.Println(resource1)
    
    resource2 := "open resource2"
    fmt.Println(resource2)
    
    // Simulate error
    if true {
        return errors.New("something went wrong")
    }
    
    // Cleanup code
    fmt.Println("closing resource2")
    fmt.Println("closing resource1")
    return nil
}

The example shows how goto could help with resource cleanup. In real code, you'd use defer for most cases, but goto remains an option for complex scenarios.

Goto with conditional jumps

goto can implement conditional jumps similar to if-else logic. This example demonstrates alternative control flow.

conditional_goto.go
package main

import "fmt"

func main() {
    num := 7
    
    if num%2 == 0 {
        goto even
    } else {
        goto odd
    }
    
even:
    fmt.Println("Number is even")
    return
    
odd:
    fmt.Println("Number is odd")
}

The program checks if a number is even or odd using goto statements. While not the best approach for this simple case, it shows conditional jumps.

Goto limitations

Go imposes restrictions on goto to prevent problematic jumps. This example shows invalid goto usage that would cause compilation errors.

invalid_goto.go
package main

import "fmt"

func main() {
    // This would cause a compile error:
    // goto skip
    // x := 5
    // skip:
    // fmt.Println(x)
    
    // Correct approach:
    x := 5
    goto skip
    fmt.Println("This won't print")
skip:
    fmt.Println(x)
}

You cannot jump over variable declarations or into other blocks. The commented code shows invalid usage, while the active code demonstrates proper goto usage.

State machine with goto

goto can implement simple state machines. This example shows a three-state machine processing input.

state_machine.go
package main

import "fmt"

func main() {
    state := "start"
    
start:
    fmt.Println("State: start")
    state = "process"
    goto process
    
process:
    fmt.Println("State: process")
    state = "end"
    goto end
    
end:
    fmt.Println("State: end")
}

The program moves through three states using goto statements. Each label represents a different state in the machine's execution flow.

Goto vs other control structures

This example contrasts goto with standard control structures to show when goto might be appropriate.

control_comparison.go
package main

import "fmt"

func main() {
    // Standard loop with break
    for i := 0; i < 10; i++ {
        if i == 5 {
            break
        }
        fmt.Println(i)
    }
    
    // Equivalent with goto
    i := 0
loop:
    if i < 10 {
        if i == 5 {
            goto end
        }
        fmt.Println(i)
        i++
        goto loop
    }
end:
}

The first loop uses standard break, while the second implements similar logic with goto. In most cases, standard control structures are preferable to goto.

Source

Go language specification

This tutorial covered the goto keyword in Go with practical examples of controlled jumps in various scenarios.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.