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
- 01
Register first
godefer closeA()Arguments are evaluated now
- 02
Register second
godefer closeB()This call is stacked above A
- 03
Return
gocloseB(); 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.
Read and predict
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.
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.