defer知识点汇总
汇总概述
- 多defer的执行本质就是一个栈,后进先出
- 正常情况下,return之后才会执行defer
- 函数有返回值变量名,这首先这个变量初始化为零值,当这个变量的生命周期会在defer执行完后
- 函数里面的defer不是总会执行的,panic后面的defer是无法执行到的.(无论外面有没有捕捉)
- 如果捕捉,那么调用这个函数的外层函数就能正常执行
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