Go defer
last modified April 11, 2024
In this article we show how to delay execution with defer statement in Golang.
The defer
statement defers the execution of a function until the
surrounding function returns. The deferred call's arguments are evaluated
immediately.
The defer
statement adds the function call following the defer
keyword onto a stack. Since the calls are placed on a stack, they are called in
last-in-first-out (LIFO) order.
One of the common uses of the defer
statement is to clean up
resources, such as open files, network connections, or database handles.
$ go version go version go1.22.2 linux/amd64
We use Go version 1.22.2.
Go defer statement
The following is a simple demonstration of the Go defer
statement.
package main import "fmt" func main() { defer fmt.Println("sky") fmt.Println("falcon") }
We have two Println
function calls. The first one is delayed with
the defer
keyword.
$ go run simple.go falcon sky
Go defer arguments evaluation
The arguments of a deferred function are evaluated immediately.
package main import "fmt" func main() { fmt.Println("start") for i := 1; i <= 5; i++ { defer fmt.Println(i) } fmt.Println("end") }
The defer
statement is placed inside the for loop. The
i
variable is evaluated during the loop execution.
$ go run arg_eval.go start end 5 4 3 2 1
Go defer function call order
The deferred function calls are placed on a stack and are called in last-in-first-out (LIFO) order.
package main import "fmt" func main() { defer fmt.Println("one") defer fmt.Println("two") defer fmt.Println("three") defer fmt.Println("four") defer fmt.Println("4") defer fmt.Println("3") defer fmt.Println("2") defer fmt.Println("1") }
The defer fmt.Println("one")
is deffered first and is executed
last. The defer fmt.Println("1")
is deffered last and is executed
first.
$ go run defer_order.go 1 2 3 4 four three two one
Go defer resource release
The defer
statement is often used when releasing necessary
resources such as opened files.
sky cloud cup wood rock sea tree oil book falcon
This is the words.txt
file.
package main import ( "bufio" "fmt" "log" "os" ) func main() { f, err := os.Open("words.txt") if err != nil { log.Fatal(err) } defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { fmt.Println(scanner.Text()) } if err := scanner.Err(); err != nil { log.Fatal(err) } }
In the code example, we read an opened file line by line.
f, err := os.Open("words.txt") if err != nil { log.Fatal(err) } defer f.Close()
After opening the words.txt
file and checking for errors, we
defer the Close
method. It releases the opened file at the end
of the main
function.
Go defer with panic
The deferred function call is executed even when the function panics.
package main import "fmt" func main() { defer fmt.Println("sky") panic("terminating") fmt.Println("falcon") }
The example calls panic
after deferring a Println
function; it is nevertheless executed.
$ go run defpanic.go sky panic: terminating goroutine 1 [running]: main.main() /home/janbodnar/Documents/prog/golang/defer/defpanic/defpanic.go:7 +0xb9 exit status 2
Source
The Go Programming Language Specification
In this article we have covered the defer statement in Golang.
Author
List all Go tutorials.