golang 中多个 defer 的执行顺序

引用 Ture Go 中的一个示例:

package main

import "fmt"

func main() {
    fmt.Println("counting")

    for i := 0; i < 10; i++ {
        defer fmt.Println(i)
    }

    fmt.Println("done")
}

程序执行结果为:

counting
done
9
8
7
6
5
4
3
2
1
0
deferFILO
id1id2id1id2Closeid1
func fun() {
    id1 := Open()

    ...
    id2 := id1.Open()

    ...

    id2.Close()

    id1.Close()
}
deferOpendefer Close
func fun() {
    id1 := Open()
    defer id1.Close()
    ...
    id2 := id1.Open()
    id2.Close()
    ...

}

defer 压入栈的是值,如果为函数,则可以修改变量值

func c() (i int) {
    defer func() { i++ }()
    return 1
}
i++
deferdeferpanic
package main

import "fmt"

func main() {
    f()
    fmt.Println("Returned normally from f.")
}

func f() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in f", r)
        }
    }()
    fmt.Println("Calling g.")
    g(0)
    fmt.Println("Returned normally from g.")
}

func g(i int) {
    if i > 3 {
        fmt.Println("Panicking!")
        panic(fmt.Sprintf("%v", i))
    }
    defer fmt.Println("Defer in g", i)
    fmt.Println("Printing in g", i)
    g(i + 1)
}

执行结果为:

Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recovered in f 4
Returned normally from f.