Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The Go if statement supports an optional initialization statement executed immediately before the condition is evaluated. This construct allows for the declaration and initialization of variables strictly within the lexical scope of the conditional block, preventing namespace pollution in the enclosing scope.

Syntax

The initialization statement is separated from the boolean condition by a semicolon (;).
if initialization_statement; condition {
    // execution block
}

Execution Mechanics

  1. Initialization: The initialization_statement (typically a short variable declaration :=, a simple assignment =, or a function call) is executed exactly once.
  2. Evaluation: The condition is evaluated. It must resolve to a typed or untyped boolean value.
  3. Branching: If the condition evaluates to true, the if block executes. If false, control flow proceeds to the else if or else blocks, if present.

Lexical Scoping and Lifetime

Variables declared within the initialization statement are block-scoped. Their lexical visibility is restricted to:
  • The body of the if block.
  • The condition and body of any attached else if blocks.
  • The body of any attached else block.
While the lexical scope of these variables is strictly confined to the if-else chain, their lifetime is determined by Go’s escape analysis and reachability rules. If a reference to the initialized variable (such as a pointer or a closure) escapes the block, the variable is allocated on the heap and will outlive the if statement.
package main

import "fmt"

func computeValue() int {
    return 10
}

func main() {
    if x := computeValue(); x > 10 {
        fmt.Println("x is greater than 10:", x)
    } else if x == 10 {
        // x is still in scope here
        fmt.Println("x is exactly 10:", x)
    } else {
        // x is still in scope here
        fmt.Println("x is less than 10:", x)
    }

    // fmt.Println(x) // Compilation error: undefined: x
}

else if Initialization

The else if branches can also declare their own initialization statements. This creates further nested implicit blocks. Variables declared in an else if initialization are scoped to that specific else if block and any subsequent else if or else blocks in the chain. They do not affect preceding blocks, but they do inherit visibility of variables declared in preceding if or else if initializations.
package main

import "fmt"

func computePrimary() int { return 5 }
func computeSecondary() int { return 15 }

func main() {
    if x := computePrimary(); x > 10 {
        fmt.Println("Primary passed:", x)
    } else if y := computeSecondary(); y > 10 {
        // Both x and y are in scope here
        fmt.Printf("Primary failed (%d), but secondary passed (%d)\n", x, y)
    } else {
        // Both x and y are in scope here
        fmt.Printf("Both failed. x: %d, y: %d\n", x, y)
    }
}

Variable Shadowing

Because the initialization statement creates a new lexical block, using the short variable declaration (:=) will shadow variables of the same name declared in the outer enclosing scope. To mutate an outer variable rather than shadowing it, the standard assignment operator (=) must be used instead of the short variable declaration.
package main

import "fmt"

func getStatus() int {
    return 200
}

func main() {
    count := 100 // Outer scope variable

    if count := 5; count < 10 {
        // Inner 'count' (5) shadows outer 'count' (100)
        fmt.Println("Inner count:", count) 
    }

    // Outer 'count' remains unmodified
    fmt.Println("Outer count:", count) // Prints 100

    var status int

    // Mutates the outer 'status' variable using standard assignment
    if status = getStatus(); status == 200 {
        fmt.Println("Status is OK:", status)
    }
}
Master Go with Deep Grasping Methodology!Learn More