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