golang recover函数使用的坑怎么解决

2023-04-26,

这篇文章主要讲解了“golang recover函数使用的坑怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang recover函数使用的坑怎么解决”吧!

一,正常情况下

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。

感谢各位的阅读,以上就是“golang recover函数使用的坑怎么解决”的内容了,经过本文的学习后,相信大家对golang recover函数使用的坑怎么解决这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是本站,小编将为大家推送更多相关知识点的文章,欢迎关注!

《golang recover函数使用的坑怎么解决.doc》

下载本文的Word格式文档,以方便收藏与打印。