मुख्य सामग्री पर जाएं
eLearner.app
मॉड्यूल 3 · पाठ 5 का 5पाठ्यक्रम में 15/50~12 min
मॉड्यूल पाठ (5/5)

`स्थगित`: गारंटीकृत सफ़ाई

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

Go
f, err := os.Open(path)
if err != nil {
    return err
}
defer f.Close()   // chiamata SEMPRE all'uscita della funzione

// ... usa f liberamente ...
return nil

Typical: 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:

Go
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:

Go
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1

This 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:

Go
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.

Go
// 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

व्यायाम#go.m3.l5.e1
प्रयास: 0लोड हो रहा है...

Print 'inizio', then defer the print of 'fine' with defer, then print 'mezzo'. The output must be: inizio / mezzo / fine.

संपादक लोड हो रहा है...
संकेत दिखाएँ

The defer runs when main() is about to return.

3 प्रयासों के बाद समाधान उपलब्ध है

व्यायाम#go.m3.l5.e2
प्रयास: 0लोड हो रहा है...

Write three consecutive defers that print 1, 2 and 3 in that order in the code. The output will be 3 / 2 / 1 (LIFO).

संपादक लोड हो रहा है...
संकेत दिखाएँ

Three defers in sequence; remember they execute in reverse order.

3 प्रयासों के बाद समाधान उपलब्ध है

Quiz#go.m3.l5.e3
तैयार

What does this print? (note: defer arguments are evaluated immediately)

Go
x := 10
defer fmt.Println(x)
x = 99
उत्तर विकल्प

Recap

  • 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 a panic (rare, at boundaries).
  • Never defer inside a long loop: it accumulates until the outer function returns.