Errors · 3 MIN READ
defer runs last in, first out
Release what you acquired, in the right order, on every path.
A deferred call runs when the function returns, whichever return it was, and deferred calls run in reverse order. That is what makes acquire-then-defer-release safe against every early return an error check introduces.
The argument to a deferred call is evaluated immediately; only the call is postponed. This surprises people exactly once.
SEE THE IDEA
Cleanup belongs next to successful acquisition
- 01
Acquire
goresource, err := open()Handle a failure first
- 02
Register
godefer resource.Close()Cleanup is now tied to this function
- 03
Exit
goreturn resultDeferred cleanup runs before the caller continues
All ordinary return paths pass through the registered cleanup.
In practice
Register a close only after acquisition succeeds. Defer also runs during panic unwinding in the same goroutine. If closing can report a relevant failure, decide how that error participates in the result rather than discarding it by habit.
Watch out
Calling os.Exit does not run deferred functions. A defer in a long loop also waits until the surrounding function exits.
Read and predict
package main
import "fmt"
func main() {
for i := 1; i <= 3; i++ {
defer fmt.Print(i, " ")
}
fmt.Print("end ")
}In what order do the numbers print?
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.