How to defer a function call

yourbasic.org/golang

A deferred function is executed when the surrounding function returns.

Basics

A defer statement postpones the execution of a function until the surrounding function returns.

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

Deferred calls are executed even when the function panics.

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

goroutine 1 [running]:
main.main()
    ../main.go:3 +0xa0

Execution order

The deferred call’s arguments are evaluated immediately, even though the function call is not executed until the surrounding function returns.

If there are several deferred function calls, the are executed in last-in-first-out order.

func main() {
    fmt.Println("Hello")
    for i := 1; i <= 3; i++ {
        defer fmt.Println(i)
    }
    fmt.Println("World")
}
Hello
World
3
2
1

Return values

Deferred functions may access and modify the surrounding function’s named return parameters.

In this example, the foo function returns “Change World”.

func foo() (result string) {
    defer func() {
        result = "Change World" // change value at the very last moment
    }()
    return "Hello World"
}

Clean-up (example)

Defer is commonly used to perform clean-up actions, such as closing a file or unlocking a mutex. In this example defer statements are used to ensure that all files are closed before leaving the CopyFile function, whichever way that happens.

func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    defer src.Close()

    dst, err := os.Create(dstName)
    if err != nil {
        return
    }
    defer dst.Close()

    return io.Copy(dst, src)
}

Recover from panic (example)

The Recover from a panic article demonstrates how to use a defer statement to recover from a panic and update the return value.

Share this page: