这篇文章主要讲解了“golang recover函数使用的坑怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang recover函数使用的坑怎么解决”吧!
一,正常情况下
package mainimport "fmt"func main(){ defer func(){ if err := recover();err != nil{ fmt.Printf("err = %v",err) } }() panic("a panic")}打印结果:err = a panicProcess finished with exit code 0
能正常catch panic
二, goroutine中panic
之前线上环境出现过接口出现panic导致服务不可用的情况,于是同事就直接在main函数加了个recover认为万事无忧了。实际上recover并不能捕捉到协程中的panic。
package mainimport "fmt"func main(){ defer func(){ if err := recover();err != nil{ fmt.Printf("err = %v",err) } }() go func(){ panic("a panic") }() select{}}打印结果:panic: a panicgoroutine 6 [running]:main.main.func2() I:/goProject/catchPanic.go:13 +0x40created by main.main I:/goProject/catchPanic.go:12 +0x5e
实际上还是会panic导致服务不可用。
正确写法
package mainimport "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 +0x41err = a panicProcess finished with exit code 2
可以看到panic被正常捕捉,同时因为select语句陷入阻塞,报了一个死锁的错。
三,间接调用recover
在我想要把recover封装成成一个函数的时候,发现recover并没有生效,因为recover只有在被defer语句直接调用的时候才会生效。当recover在其他函数内部的时候无法正确捕捉到panic。
package mainimport "fmt"func main(){ defer cover() panic("a panic")}func cover(){ defer func(){ if err := recover();err!= nil{ fmt.Println(err) } }()}返回值:panic: a panicgoroutine 1 [running]:main.main() I:/goProject/catchPanic.go:7 +0x62
四,nil panic
panic要被捕捉,还需要满足一种条件,就是panic不是nil panic,否则在进行捕获判断的时候无法知道是panic没有发生还是panic本身就是nil。
例如以下代码
package mainimport "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函数使用的坑怎么解决这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!