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 defer statement in Go schedules a function call to be executed immediately before the surrounding function returns. It pushes the deferred function call onto an internal stack, guaranteeing execution whether the surrounding function terminates normally (via a return statement) or abruptly (via a panic). However, deferred functions are not executed if the program terminates directly via os.Exit() or functions that call it internally (such as log.Fatal()).
defer functionCall(arguments)
The behavior of defer is governed by three strict mechanical rules regarding evaluation, execution order, and return value interaction.

1. Immediate Argument Evaluation

The arguments passed to a deferred function are evaluated at the exact moment the defer statement is encountered during execution, not when the deferred function is eventually invoked.
package main

import "fmt"

func main() {
    i := 0
    // The value of 'i' (0) is evaluated and saved here.
    defer fmt.Println(i) 
    i++
    // Prints 0, not 1.
}
Note: If the deferred function is a method, the receiver is also evaluated immediately.

2. LIFO Execution Order

When multiple defer statements are declared within the same function, they are pushed onto a call stack. Upon the surrounding function’s return, these deferred calls are popped off the stack and executed in Last-In, First-Out (LIFO) order.
package main

import "fmt"

func main() {
    for i := 0; i < 3; i++ {
        defer fmt.Print(i)
    }
    // Prints: 210
}

3. Interaction with Named Return Values

Deferred functions are executed after the surrounding function’s return statement updates the return variables, but before the function actually yields control back to its caller. Consequently, a deferred anonymous function can read and modify the surrounding function’s named return values.
package main

import "fmt"

func modifyReturn() (result int) {
    defer func() {
        // Modifies the named return value after the return statement executes
        result *= 2 
    }()
    return 5 // result is set to 5, then deferred function runs, changing result to 10
}

func main() {
    fmt.Println(modifyReturn()) // Prints: 10
}

Scope and Memory Considerations

A critical technical distinction in Go is that defer is bound to function scope, not block scope. If a defer statement is placed inside a nested lexical block (such as a for loop), the deferred function will not execute when the block terminates. It will only execute when the parent function returns.
package main

import "fmt"

func main() {
    for i := 0; i < 10000; i++ {
        // WARNING: These are pushed to the function's defer stack 10,000 times.
        // They do not execute at the end of each loop iteration.
        defer fmt.Sprint(i) 
    }
    // All 10,000 deferred calls execute here, right before main returns.
}
Because the defer stack allocates memory for each deferred call and its evaluated arguments, placing defer inside unbounded or large loops can lead to excessive memory consumption or stack overflows. To force block-level defer execution, the block must be wrapped in an anonymous function (or closure) that is invoked immediately.
Master Go with Deep Grasping Methodology!Learn More