golang recover函数使用中的一些坑解析

 更新时间:2023年03月19日 11:22:07   作者:机器马喝啤酒  
这篇文章主要为大家介绍了golang recover函数使用中的一些坑解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

众所周知golang 中recover函数可以捕捉panic,防止在出现异常的情况下服务整个不可用。然而某些情况下recover也无法catch panic。下面就会说一些这些情况。

一,正常情况下

package main
import "fmt"
func main(){
    defer func(){
        if err := recover();err != nil{
            fmt.Printf("err = %v",err)
        }
    }()
    panic("a panic")
}
打印结果:
err = a panic
Process finished with exit code 0

能正常catch panic

二, goroutine中panic 

之前线上环境出现过接口出现panic导致服务不可用的情况,于是同事就直接在main函数加了个recover认为万事无忧了。实际上recover并不能捕捉到协程中的panic。

package main
import "fmt"
func main(){
    defer func(){
        if err := recover();err != nil{
            fmt.Printf("err = %v",err)
        }
    }()
    go func(){
        panic("a panic")
    }()
    select{}
}
打印结果:
panic: a panic
goroutine 6 [running]:
main.main.func2()
    I:/goProject/catchPanic.go:13 +0x40
created by main.main
    I:/goProject/catchPanic.go:12 +0x5e

实际上还是会panic导致服务不可用。

正确写法

package main
import "fmt"
func main(){
    go func(){
        defer func(){
            if err := recover();err != nil{
                fmt.Printf("err = %v",err)
            }
        }()
        panic("a panic")
    }()
    select {}
}
返回值:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select (no cases)]:
main.main()
    I:/goProject/catchPanic.go:15 +0x41
err = a panic
Process finished with exit code 2

可以看到panic被正常捕捉,同时因为select语句陷入阻塞,报了一个死锁的错。

三,间接调用recover

在我想要把recover封装成成一个函数的时候,发现recover并没有生效,因为recover只有在被defer语句直接调用的时候才会生效。当recover在其他函数内部的时候无法正确捕捉到panic。

package main
import "fmt"
func main(){
    defer cover()
    panic("a panic")
}
func cover(){
    defer func(){
        if err := recover();err!= nil{
            fmt.Println(err)
        }
    }()
}
返回值:
panic: a panic
goroutine 1 [running]:
main.main()
    I:/goProject/catchPanic.go:7 +0x62

四,nil panic

panic要被捕捉,还需要满足一种条件,就是panic不是nil panic,否则在进行捕获判断的时候无法知道是panic没有发生还是panic本身就是nil。

例如以下代码

package main
import "fmt"
func main() {
    defer func(){
        if err := recover();err != nil{
            fmt.Println(err)
        }
        fmt.Println("after recover")
    }()
    panic(nil)
    select{}
}
返回值:
after recover

recover并没有正确处理异常,因为异常的值为nil。

五,总结

这篇文章讲述了三种recover会失效的情况。

  •  携程中出现panic
  • defer不直接调用recover
  • panic的值为nil值

写代码的时候需要注意避免因为这几种情况的出现而导致服务不可用。以上就是golang新手常遇见的一些坑。

以上就是golang recover函数使用中的一些坑解析的详细内容,更多关于golang recover函数坑的资料请关注脚本之家其它相关文章!

相关文章

  • Golang教程之不可重入函数的实现方法

    Golang教程之不可重入函数的实现方法

    这篇文章主要给大家介绍了关于Golang教程之不可重入函数的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • Golang使用Gin框架实现HTTP上传文件过程介绍

    Golang使用Gin框架实现HTTP上传文件过程介绍

    由于需求中有文件上传这一个需求,在这里我们就学习一下go语言如何上传文件。本文主要通过表单的方式进行文件上传操作,本文实例为大家分享了Go实现文件上传操作的具体代码,供大家参考,具体内容如下
    2023-04-04
  • 基于Go语言实现一个并发下载器

    基于Go语言实现一个并发下载器

    这篇文章主要为大家详细介绍了如何利用GO语言实现一个并发的文件下载器,可以在不重新启动整个下载的情况下处理错误,感兴趣的小伙伴可以了解一下
    2023-10-10
  • 一文带你深入了解Go语言中的事务

    一文带你深入了解Go语言中的事务

    事务中止时,你结束事务了吗?在开发时有可能就会犯这样的错误,其问题就是你在提交事务时,如果中间有其他业务就取消操作,那么事务也关闭了吗?本文就来详细讲讲
    2023-04-04
  • golang 实现Location跳转方式

    golang 实现Location跳转方式

    这篇文章主要介绍了golang 实现Location跳转方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 浅析Go语言中的map数据结构是如何实现的

    浅析Go语言中的map数据结构是如何实现的

    在 Go 中,map 是一种用于存储键值对的数据结构,它提供了一种快速查找和访问数据的方式,下面我们就来看看Go语言中是如何实现map数据结构的吧
    2024-03-03
  • Goland 断点调试Debug的操作

    Goland 断点调试Debug的操作

    这篇文章主要介绍了Goland 断点调试Debug的操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • go语言中的map如何解决散列性能下降

    go语言中的map如何解决散列性能下降

    近期对go语言的map进行深入了解和探究,其中关于map解决大量冲突的扩容操作设计的十分巧妙,所以笔者特地整理了这篇文章来探讨一下go语言中map如何解决散列性能下降,文中有相关的代码示例供大家参考,需要的朋友可以参考下
    2024-03-03
  • GO语言ini配置文件的读取的操作

    GO语言ini配置文件的读取的操作

    这篇文章主要介绍了GO语言ini配置文件的读取的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 使用golang实现一个MapReduce的示例代码

    使用golang实现一个MapReduce的示例代码

    这篇文章主要给大家介绍了关于如何使用golang实现一个MapReduce,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-09-09

最新评论