Go’s Defer statement

2021.05.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

Defer statement is used to postpone the execution of following function. The function is called even if the program panics. Let's take a closer look at how to use it.

Basics

For those coming from other languages like for example Python, defer statement is somewhat similar to Python's try/except/finally, where Go's defer is the finally part. Defer postpones execution of function until the surrounding function returns.

In below example we have two prints, but the first one is prefixed with defer statement. It is that print that will be executed when the main function returns.

func main() {
    defer fmt.Println("World")
    fmt.Println("Hello")
}

The output is the following

Hello
World

Any function prefixed with defer will be executed even if the program panics.

func main() {
    defer fmt.Println("World")
    panic("Something went wrong")
    fmt.Println("Hello")
}

In the output of the program we can see that "World" has been printed out even though the program paniced"

World
panic: Something went wrong

goroutine 1 [running]:
main.main()
        /home/michal/tmp_scripts/defer.go:7 +0x95
exit status 2

Order of execution

If there are several defer calls, the functions are called last-in-first-out order. We will call print 3 times with different messages and see what happens.

func main() {
    defer fmt.Println("Print #1")
    defer fmt.Println("Print #2")
    defer fmt.Println("Print #3")
}

As seen below, even though the Print #1 was defined first it was called last, and Print #3 was defined last, it executed first.

Print #3
Print #2
Print #1

Deferred anonymous function

A deferred anonymous functions are able to access and modify return parameters of the surrounding function.

func main() {
    res := deferredFunc()
    fmt.Println(res)
}

func deferredFunc() (result string) {
    defer func() {
        result = "from deferred function"
    }()
    return "Hellow world"
}

Contrary to some expectations the output is the string coming from anonymous function instead the "Hello world" string.

from deferred function

Applications

The defer statement as stated above is similar to Python's finally in try/except block. In Go, it is used to perform clean up actions like closing a file or unlocking a mutex. These actions should be performed regardless of program running normally or panicking.

Conlusion

We discovered the behavior that defer statement has on functions it prefixes. We know that deferred function will execute even if program panics. If multiple defer statements are called, the last one will be called first and first one as last. The main functionality of defer statement is to make sure that clean up actions will be executed even in the event of panic.