← Back to Go Course | Chapter 3: Control Flow | Lesson 4 of 7

The defer Statement

defer is like leaving yourself a sticky note that says 'do this right before you leave the room', so cleanup always happens even if you leave in a hurry.
Syntax
go
defer functionCall(args)

Basic defer

A defer statement schedules a function call to execute just before the surrounding function returns, regardless of how it returns (including via panic).

This is Go's primary tool for guaranteed cleanup code, similar to finally blocks in other languages.

Example: Basic defer

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// Define the function greet
func greet() {
	// defer runs this call when the surrounding function returns
	defer fmt.Println("goodbye")
	// Print the values followed by a newline
	fmt.Println("hello")
}

// main is where the program starts running
func main() {
	greet()
}

LIFO Order of Multiple Defers

When a function has several defer statements, they execute in last-in-first-out order: the most recently deferred call runs first. This mirrors how you'd want to unwind a stack of nested resources.

Example: LIFO Order of Multiple Defers

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// defer runs this call when the surrounding function returns
	defer fmt.Println("first deferred (runs last)")
	// defer runs this call when the surrounding function returns
	defer fmt.Println("second deferred (runs middle)")
	defer fmt.Println("third deferred (runs first)")
	// Print the values followed by a newline
	fmt.Println("main body")
}

Arguments Are Evaluated Immediately

A subtlety of defer is that the arguments to the deferred function are evaluated the moment the defer statement runs, not when the deferred call actually fires later -- only the call itself is postponed.

Note: If you need the latest value at return time, defer a closure instead of a plain function call.

Example: Arguments Are Evaluated Immediately

markup
package main

import "fmt"

func main() {
	x := 1
	defer fmt.Println("deferred x was:", x) // captures x=1 now
	x = 99
	fmt.Println("current x:", x)
}

defer for Cleanup

The most common real-world use of defer is guaranteeing that a resource acquired at the start of a function -- a file, a lock, a network connection -- gets released no matter which return path the function takes.

Example: defer for Cleanup

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// Define the function process
func process() {
	// Print the values followed by a newline
	fmt.Println("acquiring resource")
	// defer runs this call when the surrounding function returns
	defer fmt.Println("releasing resource")
	// Print the values followed by a newline
	fmt.Println("using resource")
}

// main is where the program starts running
func main() {
	process()
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Deferring inside a tight loop (e.g. deferring file.Close() for thousands of files in one function) which piles up and delays cleanup until the whole function returns.
  2. Assuming deferred function arguments are evaluated when the deferred call runs, when they're actually evaluated immediately at the defer statement.
  3. Expecting multiple defers to run in the order they were written -- they actually run in last-in-first-out (LIFO) order.
Chapter Summary
  • defer schedules a function call to run right before the enclosing function returns.
  • Deferred calls run in last-in-first-out order when there are multiple defers.
  • Arguments to a deferred call are evaluated immediately, not when the deferred call actually runs.
  • defer is the idiomatic way to guarantee cleanup, like closing a file or unlocking a mutex.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.