Module lessons (5/5)
`defer`: guaranteed cleanup
defer postpones the execution of a call until the enclosing function
returns. It runs even if the function exits via panic. Multiple defers
in the same function execute in LIFO order (Last-In, First-Out).
It's the idiomatic mechanism for resource cleanup: closing files, unlocking mutexes, releasing connections, restoring state.
Syntax and canonical use case
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // chiamata SEMPRE all'uscita della funzione
// ... usa f liberamente ...
return nilTypical: f.Close(), mu.Unlock(), db.Close(), tx.Rollback(),
recover().
Arguments evaluated immediately, execution postponed
When you write defer foo(x), x is evaluated at the time of the
defer, not at execution time:
x := 10
defer fmt.Println(x) // cattura 10
x = 99
// quando la funzione ritorna stampa "10", non "99"LIFO order
Defers stack up and execute starting with the most recent:
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1This is consistent with resource semantics: the last opened is the first to be closed.
defer + recover: handling panic
defer is the only way to intercept a panic:
func safe() {
defer func() {
if r := recover(); r != nil {
fmt.Println("recuperato:", r)
}
}()
panic("boom")
}Pitfall: defer in a loop
Putting defer f.Close() in a loop accumulates defers until the end of
the function, not of each iteration. In a long loop you open many files
and only close them when the function exits: risk of file descriptor leak.
// MALE: defer accumulati
for _, path := range paths {
f, _ := os.Open(path)
defer f.Close() // chiude TUTTI alla fine della funzione esterna
// ...
}
// MEGLIO: estrai in una funzione
for _, path := range paths {
elabora(path) // ogni chiamata ha il proprio scope di defer
}Try it
Print 'inizio', then defer the print of 'fine' with defer, then print 'mezzo'. The output must be: inizio / mezzo / fine.
Show hint
The defer runs when main() is about to return.
Solution available after 3 attempts
Write three consecutive defers that print 1, 2 and 3 in that order in the code. The output will be 3 / 2 / 1 (LIFO).
Show hint
Three defers in sequence; remember they execute in reverse order.
Solution available after 3 attempts
What does this print? (note: defer arguments are evaluated immediately)
x := 10
defer fmt.Println(x)
x = 99Recap
defer call()postpones execution until the function returns.- Multiple defers = LIFO order.
- Arguments evaluated immediately, execution postponed.
- Used for deterministic cleanup: files, mutexes, connections.
defer+recover()intercepts apanic(rare, at boundaries).- Never
deferinside a long loop: it accumulates until the outer function returns.