SoFunction
Updated on 2025-04-12

Two common pitfalls and avoidance methods when using Go defer

In Go language, defer is a very powerful keyword, used to delay execution of function calls, and is usually used in scenarios such as resource release and error handling. However, with the version iteration of Go, the implementation and performance of defer are also being continuously optimized.

This article will explore the optimization mechanism of defer in Go 1.20 in depth and reveal two common pitfalls that need to be avoided when using defer.

1. Defer optimization in Go 1.20

In Go 1.13, defer's performance has been significantly improved, mainly due to the compiler's optimization of defer's stack allocation. In Go 1.20, the optimization of defer has been further enhanced, especially when dealing with defer in loops, the compiler can more intelligently determine how defer objects are allocated.

1.1 Stack allocation optimization

In Go 1.20, the compiler will automatically choose whether to allocate it on the stack or on the heap based on the usage scenario of defer. For most simple defer calls, the compiler will prioritize allocating them on the stack, avoiding the performance overhead of heap allocation.

package main

import "fmt"

func main() {
    defer ("Go 1.20 defer optimization")
    ("Start execution")
}

Output result:

Start execution
Go 1.20 defer optimization

In this example, the defer statement is allocated on the stack, which is more efficient in execution.

1.2 Defer optimization in loops

In Go 1.20, the compiler handles defers in loops smarter. If the compiler is able to determine that the loop has fewer iterations, it allocates defer on the stack, thus avoiding frequent heap allocations.

package main

import "fmt"

func main() {
    for i := 0; i < 3; i++ {
        defer ("Number of iterations:", i)
    }
    ("End of loop")
}

Output result:

End of the loop
Iterations: 2
Iterations: 1
Iterations: 0

In this example, due to the fewer loops, the compiler allocates defer on the stack, avoiding the overhead of heap allocation.

2. Two pitfalls to avoid when using defer

Although Go 1.20 optimizes defer, in some cases improper use of defer can still cause performance problems. Here are two common pitfalls:

2.1 Defer in explicit loop

Using defer in an explicit loop may cause the defer to be too long, which will affect performance. Especially when there are many loops, the defer linked list will become very large, resulting in increased memory usage and reduced performance.

package main

import "fmt"

func main() {
    for i := 0; i < 10000; i++ {
        defer ("Defer in explicit loop:", i)
    }
    ("Explanatory loop ends")
}

In this example, the defer linked list will contain 10,000 nodes, resulting in increased memory footprint and reduced performance.

2.2 Defer in implicit loop

Defers in implicit loops can also cause performance problems. For example, implicit loops implemented using goto statements can cause the defer linked list to continue to grow, affecting performance.

package main

import "fmt"
func main() {
    i := 1
food:
    defer func() {
        ("defer in implicit loop")
    }()
    if i == 1 {
        i -= 1
        goto food
    }
    ("Implicit loop ends")
}

In this example, the goto statement causes the defer linked list to continue to grow, ultimately affecting performance.

3. Summary

Go 1.20 further optimizes defer, especially when dealing with defers in loops, the compiler can more intelligently determine how defer objects are allocated. However, developers still need to pay attention to avoiding defers in explicit and implicit loops when using defers to avoid performance problems.

In actual development, if you encounter performance bottlenecks, you can use Go's performance analysis tools (such as pprof) to check whether defer is in the hotspot path and optimize according to actual conditions. By using defer rationally, developers can maximize program performance while ensuring code simplicity.

This is the end of this article about two common pitfalls and avoidance methods when using Go defer. For more relevant content on using Go defer, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!