Go: Defer statement

A deferred method call is executed just before leaving the surrounding function.

Example: Executed before normal return:

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

Output:

Hello
World

Deferred calls are executed even when the function panics.

Example: Executed during panic:

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

Output:

World
panic: Eeek

<stack trace...>

A deferred function's arguments are evaluated when the defer statement executes.

Deferred function calls are executed in last-in-first-out order.

Example: Three deferred calls:

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

Output:

start
end
3
2
1

Deferred functions may access and modify the surrounding function's named return parameters:

Example: Change return value at the very last moment:

func Foo() (result int) {
        defer func() {
                result = 7
        }()
        return 0
}

Foo() returns 7.

Clean-up

Defer is commonly used to perform clean-up actions, such as closing a file or unlocking a mutex.

Example: Here 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

The article Recover from a panic demonstrates how to use a defer statement when recovering from a panic.

Comments

Be the first to comment!