defer
defer is a control flow statement in Go that schedules a function call to run when the surrounding function returns. It is commonly used for cleanup tasks such as closing files or releasing locks.
Syntax
// Schedules a function call to run when the surrounding function returns.
defer functionCall
// Multiple defers are executed in LIFO (last in, first out) order.
defer fmt.Println("1st") // Executed 3rd.
defer fmt.Println("2nd") // Executed 2nd.
defer fmt.Println("3rd") // Executed 1st.
// Arguments are evaluated immediately when defer is encountered.
x := 10
defer fmt.Println(x) // Prints 10 (even if x changes later).
x = 20
Characteristics of defer
| Feature | Description |
|---|---|
| LIFO order | When multiple defers are registered, the last one registered is executed first. |
| Immediate argument evaluation | Arguments to a deferred call are evaluated when the defer statement is reached, not when the function executes. |
| Named return values | A deferred function can modify named return values, affecting what the function ultimately returns. |
| Runs on panic | Deferred functions run even when a panic occurs, making them useful in combination with recover(). |
Sample Code
package main
import "fmt"
// Pattern for releasing resources using defer.
func readFile(name string) {
fmt.Printf("Opening file '%s'\n", name)
defer fmt.Printf("Closing file '%s'\n", name) // Always runs when the function returns.
// Main file processing (simulated here)
fmt.Println("Reading file...")
fmt.Println("Done reading")
// When the function returns here, the deferred call runs.
}
// Demonstrates LIFO execution order with multiple defers.
func multiDefer() {
fmt.Println("Function start")
defer fmt.Println("defer 1: executed last") // Registered 1st → executed 3rd
defer fmt.Println("defer 2: executed second") // Registered 2nd → executed 2nd
defer fmt.Println("defer 3: executed first") // Registered 3rd → executed 1st
fmt.Println("End of function body")
}
// Uses defer to modify a named return value.
func divide(a, b float64) (result float64, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("an error occurred: %v", r)
}
}()
result = a / b
return
}
func main() {
readFile("data.txt")
fmt.Println()
multiDefer()
fmt.Println()
result, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Printf("10 ÷ 2 = %.1f\n", result)
}
}
Notes
defer is a keyword that schedules cleanup work to run when a function returns. It is widely used to ensure resources are released reliably — for example, closing a file with f.Close() or unlocking a mutex with mu.Unlock(). Multiple deferred calls execute in LIFO order, so nested resources are released in reverse order of acquisition.
Using defer inside a loop causes deferred calls to accumulate until the enclosing function returns, not at the end of each iteration. If you need to release a resource immediately within a loop, either extract the loop body into a separate function that uses defer, or release the resource manually without defer.
For how defer behaves during a panic, see also panic() / recover().
If you find any errors or copyright issues, please contact us.