The := operator in Go is failing because you’re trying to use it to assign a value to a variable that has already been declared in the same scope.

Here’s a breakdown of why this happens and how to fix it, covering all the common scenarios:

Scope Shadowing with :=

The := operator is a shorthand for declaring and initializing a variable. Crucially, it only works if the variable on the left-hand side hasn’t been declared in the current scope. If it has, Go throws the "no new variables on left side of :=" error.

Common Causes and Fixes

  1. Re-declaring a variable in the same block:

    This is the most frequent culprit. You might have a variable declared earlier in a for loop, an if statement, or just a sequential block of code, and then you try to use := again for it.

    Diagnosis: Look for multiple := declarations for the same variable name within the same curly braces {}.

    Example of the error:

    package main
    
    import "fmt"
    
    func main() {
        x := 10 // First declaration
        fmt.Println(x)
        x := 20 // Error here! Redeclaring x with :=
        fmt.Println(x)
    }
    

    Fix: Use the = assignment operator instead of := for subsequent assignments to an already declared variable.

    package main
    
    import "fmt"
    
    func main() {
        x := 10 // First declaration
        fmt.Println(x)
        x = 20 // Correct: Use = for assignment
        fmt.Println(x)
    }
    

    Why it works: The = operator assigns a new value to an existing variable. The := operator, when used with an already declared variable, must also declare a new variable, which is what Go prevents.

  2. for loop initialization and :=:

    A common pattern is to declare a loop control variable using := and then try to re-declare it inside the loop body.

    Diagnosis: Check for loop conditions and the first statement inside the loop body.

    Example of the error:

    package main
    
    import "fmt"
    
    func main() {
        for i := 0; i < 3; i++ { // i is declared here with :=
            fmt.Println(i)
            // Imagine some logic that might accidentally re-declare i
            // This is a simplified example to show the error context
            // In real code, this might be nested within another if or func call
            // that re-declares i locally.
            // For demonstration:
            // if true {
            //     i := 10 // This would cause the error if i was accessible here
            // }
        }
    
        // A more direct example of the error within a loop body:
        for j := 0; j < 1; j++ {
            fmt.Println("outer", j)
            if true {
                // j := 100 // This would error because j is already declared in the outer scope
            }
        }
    }
    

    Fix: If you need to reassign a variable within a loop, use =. If you need a new variable with the same name in a nested scope, Go will prevent it if the outer variable is still in scope. The typical fix is to use a different name or ensure the nested declaration is truly distinct.

    package main
    
    import "fmt"
    
    func main() {
        for i := 0; i < 3; i++ { // i is declared here with :=
            fmt.Println(i)
            // If you needed to assign to i again:
            // i = i * 2 // This would be valid if the loop logic required it
        }
    
        // Example of fixing a nested scope issue
        for k := 0; k < 1; k++ {
            fmt.Println("outer", k)
            if true {
                // Declare a NEW variable named 'innerK' instead of trying to redeclare 'k'
                innerK := 100
                fmt.Println("inner", innerK)
            }
        }
    }
    

    Why it works: The for loop’s initialization part (i := 0) declares i for the scope of the loop. Any attempt to := declare i again within that same loop scope will fail. Using = assigns to the existing i.

  3. Function parameters and :=:

    Function parameters are considered declared variables within the function’s scope. You cannot re-declare them using := inside the function.

    Diagnosis: Look for := declarations that use the same name as a function parameter.

    Example of the error:

    package main
    
    import "fmt"
    
    func process(value int) { // 'value' is declared here
        fmt.Println(value)
        // value := 5 // Error here! Cannot redeclare 'value' with :=
    }
    
    func main() {
        process(10)
    }
    

    Fix: Use the = assignment operator to change the value of the parameter.

    package main
    
    import "fmt"
    
    func process(value int) { // 'value' is declared here
        fmt.Println(value)
        value = 5 // Correct: Use = for assignment
        fmt.Println(value)
    }
    
    func main() {
        process(10)
    }
    

    Why it works: Function parameters are already in scope. := requires a new variable, which is not allowed here. = simply updates the existing variable.

  4. if/else blocks and scope:

    Variables declared with := inside an if or else block are only available within that block’s scope. If you try to use := again for the same variable name in a subsequent if or else block (or after the if/else structure) where it’s already declared, you’ll get the error.

    Diagnosis: Trace variable declarations across if, else if, and else branches.

    Example of the error:

    package main
    
    import "fmt"
    
    func main() {
        var err error
        if true {
            err = fmt.Errorf("something went wrong") // Correct assignment
        }
    
        // Now, if we try to redeclare err with := in a subsequent block:
        if false {
            // err := fmt.Errorf("another thing") // ERROR: no new variables on left side of :=
        }
    }
    

    Fix: Use = for reassignment if the variable is already declared in an outer scope. If you intend to declare a new variable that happens to have the same name, ensure it’s in a distinctly separate, nested scope where the original isn’t visible, or use a different name.

    package main
    
    import "fmt"
    
    func main() {
        var err error
        if true {
            err = fmt.Errorf("something went wrong") // Assign to existing 'err'
        }
    
        // If we need to assign again:
        if false {
            err = fmt.Errorf("another thing") // Correct: assign to existing 'err'
        }
        fmt.Println(err)
    }
    

    Why it works: The err variable is declared outside the if blocks. The if blocks then assign to this existing err. If you used := inside the if block, Go would try to create a new err variable local to that if block, which is fine. But if the err was declared before the if and then you tried err := ... inside, it fails because err is already known.

  5. Multiple return values and :=:

    When a function returns multiple values, and you assign them to variables using :=, those variables are declared. If you then try to := declare one of those same variables again in the same scope, you’ll hit the error.

    Diagnosis: Examine function calls that return multiple values and subsequent := operations.

    Example of the error:

    package main
    
    import "fmt"
    
    func getCoords() (int, int) {
        return 10, 20
    }
    
    func main() {
        x, y := getCoords() // x and y are declared and initialized
        fmt.Println(x, y)
    
        // Imagine some logic where you might want to re-declare x
        // This can happen in nested scopes, or if you forget you already declared it.
        // if true {
        //    x := 5 // ERROR: no new variables on left side of :=
        // }
    }
    

    Fix: Use = to reassign.

    package main
    
    import "fmt"
    
    func getCoords() (int, int) {
        return 10, 20
    }
    
    func main() {
        x, y := getCoords() // x and y are declared and initialized
        fmt.Println(x, y)
    
        if true {
            x = 5 // Correct: assign to existing x
            fmt.Println("new x:", x)
        }
    }
    

    Why it works: The initial x, y := getCoords() declares x and y. The subsequent x = 5 assigns to the already declared x.

  6. Implicitly declared variables in switch statements:

    Similar to if/else, variables declared with := in one case of a switch statement might be visible in other case statements or the switch’s outer scope. If you try to := declare it again, you’ll get the error.

    Diagnosis: Check switch statements for := declarations.

    Example of the error:

    package main
    
    import "fmt"
    
    func main() {
        status := "processing"
        var message string
    
        switch status {
        case "processing":
            message = "Job is being processed." // Correct assignment
        case "completed":
            // message := "Job completed successfully." // ERROR if message was declared outside and assigned with :=
            message = "Job completed successfully." // Correct assignment
        default:
            // message := "Unknown status." // ERROR if message was declared outside and assigned with :=
            message = "Unknown status." // Correct assignment
        }
        fmt.Println(message)
    
        // A more direct example of the error in a switch:
        id := 1
        var result string
        switch id {
        case 1:
            result = "first"
        case 2:
            // result := "second" // ERROR: no new variables on left side of :=
        }
    }
    

    Fix: Use = for assignment if the variable is declared in an outer scope.

    package main
    
    import "fmt"
    
    func main() {
        status := "processing"
        var message string // Declared outside the switch
    
        switch status {
        case "processing":
            message = "Job is being processed." // Assign to existing 'message'
        case "completed":
            message = "Job completed successfully." // Assign to existing 'message'
        default:
            message = "Unknown status." // Assign to existing 'message'
        }
        fmt.Println(message)
    }
    

    Why it works: The message variable is declared once before the switch. Each case then assigns to this pre-declared variable. Using := would attempt to declare a new message variable local to that specific case, which is what Go disallows if message is already known.

By carefully checking the scope where the := operator is being used and ensuring you’re not attempting to declare a variable that already exists in that scope, you can resolve this common Go error. Remember to use = for subsequent assignments to existing variables.

The next error you might encounter after fixing these is likely related to uninitialized variables if you’ve overcorrected and removed all necessary declarations.

Want structured learning?

Take the full Golang course →