defer的执行顺序
多个defer出现的时候,它是一个“栈”的关系,也就是先进后出。
defer与return谁先谁后
package mainimport "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 calleddefer func called
return之后的语句先执行,defer后的语句后执行
函数返回值遇见defer情况
package mainimport "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 之前2defer: panic 之前1panic: 异常内容goroutine 1 [running]:main.defer_call()C:/Users/LZ.LI/Desktop/code/learn/main.go:17 +0x6fmain.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 mainimport ("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 mainimport "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))}输出:3421
- defer压栈function1,压栈函数地址、形参1、形参2(调用function3) —> 打印3
- defer压栈function2,压栈函数地址、形参1、形参2(调用function4) —> 打印4
- defer出栈function2, 调用function2 —> 打印2
- defer出栈function1, 调用function1—> 打印1
