浅谈defer、panic、recover 三者的用法

150 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1 Go的异常处理机制的引入

go的异常是一个interface类型

type error interface {
   Error() string
}

并且是可输出的

func methodA() {
   var err error
   fmt.Println(err)
}

func main() {
   methodA()
}

在这里插入图片描述
但是我们一般用panic函数进行捕获

func methodA() {
   var err error
   fmt.Println(err)
   panic(err)
   fmt.Println(err)
}

func main() {
   methodA()
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xrSSZHTY-1646469183671)(浅谈defer、panic、recover 三者的用法.assets/image-20220305155434559.png)]
这样的做法就会导致一个问题,那就是程序崩溃,不能向下进行继续的处理和异常的返回,因此我们必须有一个良好的异常处理机制进行对error类型的合理输出和处理。

由此,我们引入了defer+panic+recover进行Go程序异常处理

2 defer用法

defer函数类似于一个栈,常用于对流操作的close操作,具体演示下就知道了:

func def() {
   a := func() {
      fmt.Println("A")
   }
   b := func() {
      fmt.Println("B")
   }
   c := func() {
      fmt.Println("C")
   }
   defer c()
   defer b()
   defer a()
}

func main() {
   def()
}

执行结果:
在这里插入图片描述

3 panic和recover用法

为什么将这两个函数放在一起说呢,因为他们两个就相当于Java中的throw和try{...}catch{...}联合进行异常的捕获和处理,示例:

func a() {
   defer func() {
      r := recover()
      fmt.Println("panic recover", r)
   }()
   panic(1)
}

func main() {
   defer func() {
      r := recover()
      fmt.Println("main recover", r)
   }()
   a()
   fmt.Println("main")
   def()
}

在这里插入图片描述

4 总结

  • defer:异常时函数结束返回
  • panic:自定义抛出异常
  • recover:获取并输出异常