Golang defer keyword
last modified May 7, 2025
This tutorial explains how to use the defer
keyword in Go. We'll
cover defer basics with practical examples of resource cleanup and execution
control.
The defer statement postpones the execution of a function until the surrounding function returns. It's commonly used for cleanup operations like closing files or unlocking mutexes.
In Go, defer
ensures important cleanup code runs even if the
function exits early. Deferred calls execute in last-in-first-out order when
the function completes.
Basic defer example
The simplest use of defer
postpones a function call until after
the surrounding function completes. This example shows basic defer behavior.
package main import "fmt" func main() { defer fmt.Println("This prints last") fmt.Println("This prints first") fmt.Println("This prints second") }
The deferred call executes after all non-deferred statements in the function. Deferred calls are pushed onto a stack and executed in reverse order.
Defer with file operations
defer
is commonly used to ensure resources are properly closed.
This example demonstrates file cleanup with defer.
package main import ( "fmt" "os" ) func main() { file, err := os.Create("test.txt") if err != nil { panic(err) } defer file.Close() fmt.Fprintln(file, "Writing to file") fmt.Println("File operations complete") }
The file.Close() call is deferred until main() exits. This ensures the file is properly closed even if an error occurs during file operations.
Multiple defer statements
When multiple defer statements exist, they execute in reverse order. This example demonstrates the LIFO (last-in-first-out) behavior of defer.
package main import "fmt" func main() { defer fmt.Println("First defer - runs last") defer fmt.Println("Second defer - runs second") defer fmt.Println("Third defer - runs first") fmt.Println("Main function executing") }
Deferred calls are pushed onto a stack. The last defer registered is the first one executed when the function exits. This behavior is crucial for proper resource cleanup.
Defer with function arguments
Arguments to deferred functions are evaluated immediately, not when the function executes. This example shows argument evaluation timing.
package main import "fmt" func main() { i := 0 defer fmt.Println("Deferred print:", i) i++ fmt.Println("Regular print:", i) }
The deferred fmt.Println captures the value of i (0) when the defer statement is executed, not when the function exits. The regular print shows the updated value (1).
Defer in loops
Using defer inside loops requires caution as deferred calls don't execute until the function exits. This example demonstrates loop defer behavior.
package main import "fmt" func main() { for i := 0; i < 5; i++ { defer fmt.Println("Deferred in loop:", i) fmt.Println("In loop:", i) } fmt.Println("Loop completed") }
All deferred calls in the loop accumulate and execute in reverse order after the loop completes. Each iteration's defer captures the current value of i.
Defer with named return values
Deferred functions can modify named return values. This example shows how defer affects function return values.
package main import "fmt" func main() { fmt.Println("Result:", calculate()) } func calculate() (result int) { defer func() { result *= 2 }() result = 10 return }
The deferred function executes after the return statement but before the function actually returns. It doubles the named return value result.
Practical example: Database cleanup
This practical example demonstrates using defer for database connection cleanup in a real-world scenario.
package main import ( "database/sql" "fmt" "log" _ "github.com/lib/pq" ) func main() { db, err := sql.Open("postgres", "user=test dbname=test sslmode=disable") if err != nil { log.Fatal(err) } defer db.Close() rows, err := db.Query("SELECT id, name FROM users") if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var id int var name string if err := rows.Scan(&id, &name); err != nil { log.Fatal(err) } fmt.Printf("ID: %d, Name: %s\n", id, name) } if err := rows.Err(); err != nil { log.Fatal(err) } }
The example shows proper resource cleanup with defer for both the database connection and query results. This pattern ensures resources are released even if errors occur during processing.
Source
This tutorial covered the defer
keyword in Go with practical
examples of resource management and execution control.
Author
List all Golang tutorials.