Defer

A defer statement defers the execution of a function until the surrounding function returns.

The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
// Excepted results:
hello
world

Stacking defers

Deferred function calls are pushed onto a stack. When a function returns, its deferred calls are executed in last-in-first-out order.

package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
// Excepted results:
counting
done
9
8
7
6
5
4
3
2
1
0

Another example.

func trace(s string) string {
fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() {
b()
}
//Expected results:
entering: b
in b
entering: a
in a
leaving: a
leaving: b

Defer in For loop

https://stackoverflow.com/a/45620423/12339035

Question:

for rows.Next() {
fields, err := db.Query(.....)
if err != nil {
// ...
}
defer fields.Close()
// do something with `fields`
}

Right approach:

for rows.Next() {
func() {
fields, err := db.Query(...)
if err != nil {
// Handle error and return
return
}
defer fields.Close()
// do something with `fields`
}()
}

Wrong approach:

for rows.Next() {
fields, err := db.Query(.....)
if err != nil {
// ...
}
// do something with `fields`
fields.Close()
}

To learn more about defer statements read this blog post.

Last updated on