defer的执行顺序

多个defer出现的时候,它是一个“栈”的关系,也就是先进后出
defer - 图1

defer与return谁先谁后

  1. package main
  2. import "fmt"
  3. func deferFunc() int {
  4. fmt.Println("defer func called")
  5. return 0
  6. }
  7. func returnFunc() int {
  8. fmt.Println("return func called")
  9. return 0
  10. }
  11. func returnAndDefer() int {
  12. defer deferFunc()
  13. return returnFunc()
  14. }
  15. func main() {
  16. returnAndDefer()
  17. }
  18. 输出:
  19. return func called
  20. defer func called

return之后的语句先执行,defer后的语句后执行

函数返回值遇见defer情况

  1. package main
  2. import "fmt"
  3. func returnButDefer() (t int) { //t初始化0, 并且作用域为该函数全域
  4. defer func() {
  5. t = t * 10
  6. }()
  7. return 1
  8. }
  9. func main() {
  10. fmt.Println(returnButDefer())
  11. }
  12. 输出:
  13. 10

补充知识: 函数返回值
func DeferFunc1(i int) (t int) {}
其中返回值t int,这个t会在函数起始处被初始化为对应类型的零值并且作用域为整个函数。
defer - 图2
只要声明函数的返回值变量名称,就会在函数初始化时候为之赋值为0,而且在函数体作用域可见,在函数return时,t的值将会被赋值为2

defer遇见panic

defer - 图3

  1. func main() {
  2. defer_call()
  3. fmt.Println("main 正常结束")
  4. }
  5. func defer_call() {
  6. defer func() { fmt.Println("defer: panic 之前1") }()
  7. defer func() { fmt.Println("defer: panic 之前2") }()
  8. panic("异常内容") //触发defer出栈
  9. defer func() { fmt.Println("defer: panic 之后,永远执行不到") }()
  10. }
  11. 输出:
  12. defer: panic 之前2
  13. defer: panic 之前1
  14. panic: 异常内容
  15. goroutine 1 [running]:
  16. main.defer_call()
  17. C:/Users/LZ.LI/Desktop/code/learn/main.go:17 +0x6f
  18. main.main()
  19. C:/Users/LZ.LI/Desktop/code/learn/main.go:8 +0x29

捕获异常

  1. func main() {
  2. defer_call()
  3. fmt.Println("main 正常结束")
  4. }
  5. func defer_call() {
  6. defer func() {
  7. fmt.Println("defer: panic 之前1, 捕获异常")
  8. if err := recover(); err != nil {
  9. fmt.Println("recover:" , err)
  10. }
  11. }()
  12. defer func() { fmt.Println("defer: panic 之前2, 不捕获") }()
  13. panic("异常内容") //触发defer出栈
  14. defer func() { fmt.Println("defer: panic 之后, 永远执行不到") }()
  15. }
  16. 输出:
  17. defer: panic 之前2, 不捕获
  18. defer: panic 之前1, 捕获异常
  19. recover: 异常内容
  20. main 正常结束

defer中包含panic

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. defer func() {
  7. if err := recover(); err != nil{
  8. fmt.Println(err)
  9. }else {
  10. fmt.Println("fatal")
  11. }
  12. }()
  13. defer func() {
  14. panic("defer panic")
  15. }()
  16. panic("panic")
  17. }

recover会捕获最后一个异常,一个recover只能捕获一个异常,若有多个panic,则需要多个recover才能全部捕获.

defer下的函数参数包含子函数

  1. package main
  2. import "fmt"
  3. func function(index int, value int) int {
  4. fmt.Println(index)
  5. return index
  6. }
  7. func main() {
  8. defer function(1, function(3, 0))
  9. defer function(2, function(4, 0))
  10. }
  11. 输出:
  12. 3
  13. 4
  14. 2
  15. 1
  • defer压栈function1,压栈函数地址、形参1、形参2(调用function3) —> 打印3
  • defer压栈function2,压栈函数地址、形参1、形参2(调用function4) —> 打印4
  • defer出栈function2, 调用function2 —> 打印2
  • defer出栈function1, 调用function1—> 打印1