The Go compiler flagged a label defined and not used error because you’ve declared a goto or for/switch label, but your code never actually jumps to it.

Here’s the breakdown of why this happens and how to fix it, from most to least common:

1. Accidental Label Declaration

This is the most frequent culprit. You might have intended to use a label for a goto statement, or perhaps you’re thinking of a label in a different language.

Diagnosis: Look for LABEL: syntax in your code.

Fix: Simply remove the unused label and the colon.

// Before
func example() {
    myLabel: // This is the unused label
    fmt.Println("Hello")
    // No goto myLabel here
}

// After
func example() {
    fmt.Println("Hello")
}

Why it works: Removing the declaration eliminates the compiler’s complaint about an unused symbol.

2. Misplaced goto Statement

You declared a label, and you did intend to use goto, but you put the goto statement in the wrong place, or it’s unreachable.

Diagnosis: Find the label and check if there’s a goto statement that can actually execute and reach it.

Fix: Ensure the goto statement is placed before the label it refers to, and that there’s a code path where the goto will be executed.

// Before
func example() {
    fmt.Println("Start")
    goto myLabel // This goto is after the label
    fmt.Println("Middle") // Unreachable
myLabel:
    fmt.Println("End")
}

// After
func example() {
    fmt.Println("Start")
    goto myLabel // Correct placement
    fmt.Println("Middle") // This line will be skipped
myLabel:
    fmt.Println("End")
}

Why it works: The goto statement now correctly transfers control to the specified label, fulfilling the label’s purpose.

3. Unused break or continue Target Labels

While less common for goto, labels are frequently used with break and continue to exit or restart specific loops or switch statements. If you label a loop or switch but never use break LABEL or continue LABEL, the label will be unused.

Diagnosis: Search for labeled for or switch statements and check if break or continue are referencing those labels.

Fix: Either remove the label if the loop/switch doesn’t need to be broken out of or continued at a specific level, or add the break LABEL or continue LABEL statement where appropriate.

// Before
func example() {
outerLoop:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("%d, %d\n", i, j)
            // Missing break outerLoop here
        }
    }
}

// After
func example() {
outerLoop:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            fmt.Printf("%d, %d\n", i, j)
            if i == 1 && j == 1 {
                break outerLoop // Explicitly break the outer loop
            }
        }
    }
}

Why it works: The break outerLoop statement now explicitly uses the outerLoop label to exit the outer for loop, satisfying the compiler’s requirement.

4. Copy-Pasted Code with Stale Labels

When you copy code from an example or another part of your project, you might inadvertently bring along labels that are no longer relevant in the new context.

Diagnosis: Review any recently pasted code blocks for labels that don’t seem to have a clear purpose or corresponding goto/break/continue.

Fix: Remove the unused labels from the pasted code.

// Before (pasted from somewhere else)
func processData(data []int) {
    processingDone: // This label was from the original source
    for i, val := range data {
        if val < 0 {
            fmt.Printf("Skipping negative value at index %d\n", i)
            continue
        }
        // ... process val ...
    }
    // No goto processingDone
}

// After
func processData(data []int) {
    for i, val := range data {
        if val < 0 {
            fmt.Printf("Skipping negative value at index %d\n", i)
            continue
        }
        // ... process val ...
    }
}

Why it works: Removing the extraneous label cleans up the code and removes the compiler’s warning.

5. Incorrectly Scoped Labels

Labels in Go have function-level scope. This means a label declared inside a function can only be jumped to from within that same function. If you try to jump to a label from an inner function (like a closure) that isn’t defined within that inner function’s scope, you’ll get this error, or a similar scope-related one.

Diagnosis: Examine the scope of your labels and any goto or break/continue statements referencing them. Ensure they are within the same function.

Fix: Move the label declaration to a scope that encompasses the goto statement, or restructure your code to avoid needing to jump across function boundaries with goto.

// Before
func outerFunction() {
    goto myLabel // Error: myLabel is not defined in this scope

    innerFunc := func() {
    myLabel: // Label is inside the closure, but goto is outside
        fmt.Println("Inside innerFunc")
    }
    innerFunc()
}

// After (Restructure to avoid cross-scope goto)
func outerFunction() {
    innerFunc := func() {
    myLabel:
        fmt.Println("Inside innerFunc")
    }
    innerFunc()
    // If you need to jump *after* innerFunc, use a return value or flag.
}

Why it works: By ensuring the goto and its target label reside within the same function scope, you satisfy Go’s scoping rules.

6. Debugging Artifacts

Sometimes, during debugging, you might temporarily add a label and a goto to jump to a specific point for inspection. If you forget to remove it after debugging, it can lead to this error.

Diagnosis: Look for labels that seem to serve no logical purpose in the final algorithm, especially if they are near print statements or debugging logic.

Fix: Remove the debug label and any associated goto statement.

// Before
func process(items []string) {
    // ... some processing ...
    debugPoint: // Leftover from debugging
    fmt.Println("Reached this point")
    // ... rest of processing ...
}

// After
func process(items []string) {
    // ... some processing ...
    fmt.Println("Reached this point") // Or remove this print if not needed
    // ... rest of processing ...
}

Why it works: Removing the extraneous label and goto cleans up the code and resolves the compilation error.

The next error you’ll likely encounter after fixing these is a variable declared and not used error if you’ve also left unused variables lying around.

Want structured learning?

Take the full Golang course →