Skip to content
DeveloperMemos

Using Go's Defer Statement

Go, Defer Statement1 min read

In Go programming, the defer statement is a powerful construct that allows you to schedule a function call to be executed just before the surrounding function returns. It provides an elegant way to manage resources and perform cleanup operations. This article will explore the fundamentals of the defer statement and demonstrate its usefulness through various examples.

Basic Usage

The defer statement is straightforward to use. Simply prefix a function call with the defer keyword, and it will be deferred until the surrounding function completes. Let's consider a simple example to illustrate its usage:

1func main() {
2 defer fmt.Println("World")
3
4 fmt.Println("Hello")
5}

When executing this code, the output will be:

1Hello
2World

As you can see, even though we invoked fmt.Println("World") first, it was deferred until after the completion of the main function, resulting in "World" being printed last.

Resource Cleanup

One common use case for the defer statement is to ensure proper cleanup of resources, such as closing files or releasing locks, regardless of the control flow or potential errors. Consider the following example:

1func processFile(filename string) error {
2 file, err := os.Open(filename)
3 if err != nil {
4 return err
5 }
6 defer file.Close()
7
8 // Process the file here...
9
10 return nil
11}

In this example, the defer statement ensures that the file is closed before the processFile function exits, regardless of any errors encountered during processing.

Arguments Evaluation

It's worth noting that the arguments in a deferred function call are evaluated immediately, not at the time of execution. Let's see an example to understand this behavior:

1func printNumber(n int) {
2 fmt.Println(n)
3}
4
5func main() {
6 for i := 0; i < 5; i++ {
7 defer printNumber(i)
8 }
9}

The output of this code will be:

14
23
32
41
50

Here, each iteration of the loop defers the execution of printNumber(i). Since the argument i is evaluated at the time of the defer statement, the value printed reflects the current value of i.

Execution Order

When multiple defer statements are present in a function, they are executed in reverse order, similar to a stack. Consider the following example:

1func main() {
2 defer fmt.Println("First")
3 defer fmt.Println("Second")
4 defer fmt.Println("Third")
5}

In this case, the output will be:

1Third
2Second
3First

As you can see, the most recently deferred function call is executed first, followed by the next one, until all deferred calls have been executed.

Defer and Panic

When a panic occurs in Go, the deferred functions still get executed before the program terminates. This behavior allows you to perform cleanup operations even in exceptional scenarios. Here's an example:

1func cleanup() {
2 fmt.Println("Performing cleanup...")
3}
4
5func process() {
6 defer cleanup()
7
8 // Perform some work...
9
10 if err := recover(); err != nil {
11 fmt.Println("Panic occurred:", err)
12 }
13}
14
15func main() {
16 process()
17}

In this code, the cleanup function is deferred within the process function. If a panic occurs during the execution of process, the cleanup function will still be called, allowing you to release any acquired resources or perform necessary cleanup tasks.