Defer a function call (with return value)
Defer statement basics
A defer
statement postpones the execution of a function
until the surrounding function returns, either normally or through a panic.
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
Order of execution
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, they 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
Use func to return a value
Deferred anonymous 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"
}
Common applications
Defer is often used to perform clean-up actions, such as closing a file or unlocking a mutex. Such actions should be performed both when the function returns normally and when it panics.
Close a file
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)
}
Error handling: catch a panic
The Recover from a panic code example shows how to use a defer statement to recover from a panic and update the return value.