Learn Go← Dashboard

Parameters, multiple returns, variadic, closures, and defer.

defer

defer schedules a function call to run when the enclosing function returns (by return, by reaching the end, or by panicking). It's Go's answer to "try/finally" and to RAII.

The basics

go playground
Loading...

The output is:

running main
1 — first deferred
2 — middle
3 — cleanup

Deferred calls run in LIFO order (last in, first out) — like a stack. This means you can pair Open / Close in the order you intuitively want:

f, err := os.Open("data.txt")
if err != nil { return err }
defer f.Close()              // happens last, after all other work

// ... use f ...

Arguments are evaluated immediately

The arguments of a deferred call are evaluated right away, even though the call itself doesn't run until later.

go playground
Loading...

This prints:

now: 99
deferred sees: 1

To defer something that uses the current value at return time, wrap it in a closure:

defer func() { fmt.Println("now:", n) }()

Real-world uses

// 1. unlock a mutex
mu.Lock()
defer mu.Unlock()

// 2. close a network connection
conn, _ := net.Dial("tcp", addr)
defer conn.Close()

// 3. recover from a panic
defer func() {
    if r := recover(); r != nil {
        log.Println("recovered:", r)
    }
}()

We cover recover properly in chapter 15.

In what order do deferred calls run?