搜索

查看: 3043|回复: 11

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

[复制链接]
发表于 2023-5-4 17:04:19 | 显示全部楼层 |阅读模式
Editor 2023-5-4 17:04:19 3043 11 看全部
目录
  • 正文
  • 一,正常情况下
  • 二, goroutine中panic
  • 三,间接调用recover
  • 四,nil panic
  • 五,总结
    正文
    众所周知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函数坑的资料请关注知鸟论坛其它相关文章!
  • 知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-29 17:18:34 | 显示全部楼层
    掌舵的鱼1987 2023-6-29 17:18:34 看全部
    楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-29 17:20:35 | 显示全部楼层
    素色流年783 2023-6-29 17:20:35 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-29 18:58:09 | 显示全部楼层
    麻辣鸡翅 2023-6-29 18:58:09 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-29 19:40:11 | 显示全部楼层
    当当当当裤裆坦 2023-6-29 19:40:11 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-29 21:34:58 | 显示全部楼层
    伊索谗言 2023-6-29 21:34:58 看全部
    其实我一直觉得楼主的品味不错!呵呵!知鸟论坛太棒了!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-29 22:00:37 | 显示全部楼层
    123456865 2023-6-29 22:00:37 看全部
    楼主太厉害了!楼主,I*老*虎*U!我觉得知鸟论坛真是个好地方!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-29 22:03:34 | 显示全部楼层
    无人岛屿颈 2023-6-29 22:03:34 看全部
    楼主太厉害了!楼主,I*老*虎*U!我觉得知鸟论坛真是个好地方!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-30 01:27:15 | 显示全部楼层
    462710480 2023-6-30 01:27:15 看全部
    我看不错噢 谢谢楼主!知鸟论坛越来越好!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    发表于 2023-6-30 06:59:40 | 显示全部楼层
    计划你大爷计j 2023-6-30 06:59:40 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    知鸟论坛永久地址发布页:www.zn60.me
    回复

    使用道具 举报

    • 您可能感兴趣
    点击右侧快捷回复 【请勿灌水】
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则 返回列表

    RSS订阅| SiteMap| 小黑屋| 赞兔论坛
    联系邮箱E-mail:zniao@foxmail.com
    快速回复 返回顶部 返回列表