HowtoGo
Home / Language / Defer
Language

Defer

The defer statement schedules a function call to run right before its surrounding function returns, regardless of how that return happens.

defer fmt.Println("done") doesn't run immediately. It runs after greet's other statements finish, right before the function actually returns.

func greet() {
    defer fmt.Println("done")
    fmt.Println("hello")
}

Multiple defers stack up and run in last-in, first-out order. The last defer registered is the first one executed.

defer fmt.Println("first")
defer fmt.Println("second")
defer fmt.Println("third")

A deferred call's arguments are evaluated immediately, at the point of the defer statement, not when it eventually runs. Each loop iteration captures that iteration's value of i.

for i := 0; i < 3; i++ {
    defer fmt.Println(i)
}

A deferred closure can modify a named return value after the return statement has set it, since the return value isn't finalized until every deferred call has run.

func doSomething() (result int) {
    defer func() {
        result *= 2
    }()
    return 5
}

doSomething returns 10, not 5: the deferred closure doubles result after return 5 assigns it but before the function actually exits.

Terminal
$ go run defer.go
hello
done
2
1
0
12