汇总概述

  1. 多defer的执行本质就是一个栈,后进先出
  2. 正常情况下,return之后才会执行defer
  3. 函数有返回值变量名,这首先这个变量初始化为零值,当这个变量的生命周期会在defer执行完后
  4. 函数里面的defer不是总会执行的,panic后面的defer是无法执行到的.(无论外面有没有捕捉)
  5. 如果捕捉,那么调用这个函数的外层函数就能正常执行

1.没有捕捉,panic之后不会执行

遇到panic,表示这个函数栈,需要收尾了,后面的不需要执行

func main() {
    defer_call()

    fmt.Println("main 正常结束")
}

func defer_call() {
    defer func() { fmt.Println("defer: panic 之前1") }()
    defer func() { fmt.Println("defer: panic 之前2") }()
    panic("异常内容") //触发defer出栈
    defer func() { fmt.Println("defer: panic 之后,永远执行不到") }()
}

结果
defer: panic 之前2
defer: panic 之前1
panic: 异常内容
//... 异常堆栈信息

2.捕捉是需要在panic当前函数栈进行捕捉,否则会影响外层调用者.


func main() {
    //捕捉到了,当前函数调用defer_call时发生异常,后续不需要再执行了
    defer func() {
        fmt.Println(recover())
    }()
    defer_call()

    fmt.Println("main 正常结束")
}

func defer_call() {
    defer func() { fmt.Println("defer: panic 之前1") }()
    defer func() { fmt.Println("defer: panic 之前2") }()

    panic("异常内容") //触发defer出栈

    defer func() { fmt.Println("defer: panic 之后,永远执行不到") }()
}

defer: panic 之前2
defer: panic 之前1
异常内容

//--------------------------正确方式

func main() {
    defer_call()

    fmt.Println("main 正常结束")
}

func defer_call() {

    defer func() {
        fmt.Println("defer: panic 之前1, 捕获异常")
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()

    defer func() { fmt.Println("defer: panic 之前2, 不捕获") }()

    panic("异常内容") //触发defer出栈

    defer func() { fmt.Println("defer: panic 之后, 永远执行不到") }()
}

defer: panic 之前2, 不捕获
defer: panic 之前1, 捕获异常
异常内容
main 正常结束

3.defer后面的函数里面参数是子函数,那么子函数会先执行

func function(index int, value int) int {

    fmt.Println(index)

    return index
}

func main() {
    defer function(1, function(3, 0))
    defer function(2, function(4, 0))
}
3
4
2
1

发表回复