SoFunction
Updated on 2025-04-08

Deeply understand the mechanism of defer in Go

deferIt is a keyword used in Go language to delay execution of function calls, and is often used for resource cleaning (such as closing files, releasing locks) and exception handling. However, there are some hidden details in its behavior mechanism, and a little carelessness may lead to undetectable bugs. This article uses multiple intuitive examples to analyze in-depthdeferThe core mechanism.

1. Defer execution order: last in first out (LIFO)

MultipledeferStatement PressReverse execution, similar to the "last in first out" principle of stack.

Example: Execution order of multiple defers

func main() {
    defer ("defer 1")
    defer ("defer 2")
    ("main logic")
}

Output:

main logic
defer 2
defer 1

in conclusion

  • deferStatements are executed in reverse order in the registration order to ensure that dependent resources are released in the correct order (such as opening the file first and then closing).

2. Pre-calculation of defer’s parameters: the trap of value copy

deferThe parameters of   are immediately registeredPre-calculate and copy, not dynamically retrieved during execution.

Example: The impact of parameter precalculation

func main() {
    x := 10
    defer ("x:" in defer, x) // The value of x is copied at registration    x = 20
    ("x:" in main, x)
}

Output:

x: 20 in main
x: 10 in defer

in conclusion

  • If the parameter is a value type (such asintstring),deferThe current value will be copied, and subsequent modifications will not affect the registered ones.defer
  • If the parameter is a pointer or reference type (such as*intslice), the copy is the address, and subsequent modifications will affectdeferThe execution result.

3. Defer and closure: dynamically bound variables

deferIf a function uses an external variable (closure), it will refer to the variable.Latest value, not the value at the time of registration.

Example: Variable binding in closure

func main() {
    x := 10
    defer func() {
        ("x:" in defer, x) // The closure references the latest value    }()
    x = 20
    ("x:" in main, x)
}

Output:

x: 20 in main
x: 20 in defer

in conclusion

  • The variables in the closure aredeferThe value is evaluated only when executed, so it will reflect the final state of the variable.
  • If you need to fix the value in the closure, you need to pass it through parameters when registering (such asdefer func(a int) { ... }(x))。

4. Defer and return value: implicit assignment logic

deferThe behavior of modifying the return value in   depends on how the return value is defined (value returns vs pointer returns).

Example 4: Difference between value return and pointer return

// Value return: Defer modification does not affect the return valuefunc f1() int {
    x := 10
    defer func() { x++ }()
    return x // What is actually returned is a copy of x}

// Pointer return: defer modification affects return valuefunc f2() *int {
    x := 10
    defer func() { x++ }()
    return &x // Return the address of x}

func main() {
    (f1()) // Output 10    (*f2()) // Output 11}

in conclusion

  • Value returns: The return value isreturnCopy whendeferModifying the original variable will not affect the copied value.
  • Pointer return: The variable address is returned.deferModify the original variable through the address to affect the final result.

This is all about this article about the defer mechanism in Go. For more relevant content on Go defer mechanism, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!