GO:The usage of 'defer'

defer is very useful in control. It is used within a function.

If a function contains one or multiple defer command, it will not really return or finish unless all the functions followed directly by defer have finished. All the functions are called 'delayed' functions if they are on the right side of defer. You can release the resources using defer right after requesting it, in case you forget to release at the end of a function.

If the defer function has some input arguments, the input expressions will be calculated directly. But the defer function will not be executed immediately.

package main

import (
    "fmt"
)

func mixed(n,m int) (number int) {
    fmt.Println("step mixed")
    return n+m
}

func modify(n int) (number int) {
    defer func (plus int) (result int) {
        fmt.Println("Coming in defer")
        result = n + plus
        number += result
        fmt.Println(number)
        return
    }(mixed(1,2))
    fmt.Println("step 1", number)
    number++
    fmt.Println("step 2", number)
    return
}

func main() {
    modify(2)
}

The output is shown as below:

go run defer_learn.go
step mixed
step 1 0
step 2 1
Coming in defer
6

Let's see another example.

func printNumbers() {
    for i:=0; i<5; i++ {
        defer fmt.Printf("%d", i)
    }
}

The result is: 43210 not 01234 because this for loop can translate into the following statements:

fmt.Printf("%d",0)
fmt.Printf("%d",1)
fmt.Printf("%d",2)
fmt.Printf("%d",3)
fmt.Printf("%d",4)

When the function printNumbers wants to finish, it executes all defer statements using FIFO mode. So the output is 43210.

If we change the defer statement a little into this:

func printNumbers() {
    for i:=0; i<5; i++ {
        defer func() {
            fmt.Printf("%d", i)
        }()
    }
}

The result is 55555 because defer function doesn't have input argument, so it has nothing to calculate before really execution. There will be 5 fmt.Printf("%d", i) listing before printNumbers finishes where i=5 at this point of time.