Go core · 3 MIN READ

Deferred calls stack, last one first

Say the print order of three deferred calls.

Deferred calls run in last-in, first-out order when the surrounding function returns. Three defer fmt.Println(n) statements execute in the reverse of their registration order.

The deferred function and its arguments are evaluated when defer executes. A deferred closure, in contrast, may read a captured variable when it eventually runs. Keep that distinction clear when a variable changes between registration and return.

SEE THE IDEA

Deferred work unwinds in reverse order

  1. 01

    Register first

    go
    defer closeA()

    Arguments are evaluated now

  2. 02

    Register second

    go
    defer closeB()

    This call is stacked above A

  3. 03

    Return

    go
    closeB(); closeA()

    The newest deferred call runs first

Registration order and execution order point in opposite directions.

In practice

Put cleanup next to successful acquisition so later return paths cannot bypass it. The function and arguments of a deferred call are evaluated when defer executes; a deferred closure can instead read variables later. This difference explains many surprising loop and mutation examples.

Watch out

Defer runs when the surrounding function returns, not at the end of an inner block or one loop iteration.

Official reference ↗

Read and predict

go
package main

import "fmt"

func main() {
	fmt.Println("counting")
	for i := 0; i < 3; i++ {
		defer fmt.Println(i)
	}
	fmt.Println("done")
}

What does this print? The Tour's stacking-defers program.

Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.