Lesson 6 of 18

Defer

Cleaning Up After Yourself

The defer keyword schedules a function call to run when the surrounding function returns. It is Go's way of ensuring cleanup happens no matter how the function exits.

func main() {
    fmt.Println("start")
    defer fmt.Println("deferred")
    fmt.Println("end")
}
// Output:
// start
// end
// deferred

The deferred call runs after the function body completes but before it returns to the caller.

On the bridge of the Enterprise, the captain might say: "Engage! But first, make sure someone closes the shuttlebay doors." That is defer in a nutshell.

LIFO Order

When you defer multiple calls, they execute in last-in, first-out order --- like a stack:

func main() {
    defer fmt.Println("first")
    defer fmt.Println("second")
    defer fmt.Println("third")
}
// Output:
// third
// second
// first

Common Pattern: Open Then Defer Close

The most common use of defer is pairing resource acquisition with cleanup on the very next line:

f, err := os.Open("data.txt")
if err != nil {
    return err
}
defer f.Close()
// work with f...

This makes it impossible to forget to close the file, regardless of how many return paths the function has.

Arguments Are Evaluated Immediately

The arguments to a deferred call are evaluated when the defer statement executes, not when the deferred function runs:

x := 10
defer fmt.Println(x) // captures 10
x = 20
// prints 10, not 20

Defer in Loops

Be careful with defer inside loops. Deferred calls accumulate and only run when the function returns, not when the loop iteration ends:

for _, name := range files {
    f, _ := os.Open(name)
    defer f.Close() // these all pile up!
}

If you need per-iteration cleanup, extract the body into a separate function so each deferred call runs promptly.

Your Task

Write a function countdown(n int) that uses defer inside a loop to print numbers in reverse order, followed by "Go!".

For example, countdown(3) should print:

3
2
1
Go!

Hint: defer each number inside the loop. Since deferred calls execute in LIFO order, deferring 1, 2, 3 will print 3, 2, 1. Think about where "Go!" needs to appear relative to the numbers, and remember that all deferred calls execute in LIFO order --- so if you defer "Go!" before the loop, it will be at the bottom of the stack and print last.

Go runtime loading...
Loading...
Click "Run" to execute your code.