defer的执行顺序
多个defer出现的时候,它是一个“栈”的关系,也就是先进后出。
defer与return谁先谁后
package main
import "fmt"
func deferFunc() int {
fmt.Println("defer func called")
return 0
}
func returnFunc() int {
fmt.Println("return func called")
return 0
}
func returnAndDefer() int {
defer deferFunc()
return returnFunc()
}
func main() {
returnAndDefer()
}
输出:
return func called
defer func called
return之后的语句先执行,defer后的语句后执行
函数返回值遇见defer情况
package main
import "fmt"
func returnButDefer() (t int) { //t初始化0, 并且作用域为该函数全域
defer func() {
t = t * 10
}()
return 1
}
func main() {
fmt.Println(returnButDefer())
}
输出:
10
补充知识: 函数返回值
func DeferFunc1(i int) (t int) {}
其中返回值t int,这个t会在函数起始处被初始化为对应类型的零值并且作用域为整个函数。
只要声明函数的返回值变量名称,就会在函数初始化时候为之赋值为0,而且在函数体作用域可见,在函数return时,t的值将会被赋值为2
defer遇见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: 异常内容
goroutine 1 [running]:
main.defer_call()
C:/Users/LZ.LI/Desktop/code/learn/main.go:17 +0x6f
main.main()
C:/Users/LZ.LI/Desktop/code/learn/main.go:8 +0x29
捕获异常
func main() {
defer_call()
fmt.Println("main 正常结束")
}
func defer_call() {
defer func() {
fmt.Println("defer: panic 之前1, 捕获异常")
if err := recover(); err != nil {
fmt.Println("recover:" , err)
}
}()
defer func() { fmt.Println("defer: panic 之前2, 不捕获") }()
panic("异常内容") //触发defer出栈
defer func() { fmt.Println("defer: panic 之后, 永远执行不到") }()
}
输出:
defer: panic 之前2, 不捕获
defer: panic 之前1, 捕获异常
recover: 异常内容
main 正常结束
defer中包含panic
package main
import (
"fmt"
)
func main() {
defer func() {
if err := recover(); err != nil{
fmt.Println(err)
}else {
fmt.Println("fatal")
}
}()
defer func() {
panic("defer panic")
}()
panic("panic")
}
recover会捕获最后一个异常,一个recover只能捕获一个异常,若有多个panic,则需要多个recover才能全部捕获.
defer下的函数参数包含子函数
package main
import "fmt"
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
- defer压栈function1,压栈函数地址、形参1、形参2(调用function3) —> 打印3
- defer压栈function2,压栈函数地址、形参1、形参2(调用function4) —> 打印4
- defer出栈function2, 调用function2 —> 打印2
- defer出栈function1, 调用function1—> 打印1