ZetCode

Go defer

last modified December 30, 2020

Go defer tutorial shows 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 defer statement

The following is a simple demonstration of the Go defer statement.

simple.go
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.

arg_eval.go
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.

defer_order.go
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.

words.txt
sky
cloud
cup
wood
rock
sea
tree
oil
book
falcon

This is the words.txt file.

read_line_by_line.go
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 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.

defpanic.go
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

In this tutorial, we have covered the defer statement in Golang.

List all Go tutorials.