Golang是否支持全局恢复?

huangapple go评论103阅读模式
英文:

Does golang support global recovery?

问题

我有一个有很多goroutine的程序,我想要全局处理panic。看起来我必须在每个goroutine中添加一个recovery,有没有一种方法可以全局处理呢?

我写了一个测试程序,在main函数中添加了一个recover(),但它无法捕获其他goroutine中的崩溃:

  1. package main
  2. import "log"
  3. func bug2() {
  4. panic("bug2()")
  5. }
  6. func bug1() {
  7. go bug2()
  8. }
  9. func main() {
  10. defer func() {
  11. if r := recover(); r != nil {
  12. log.Println("catched")
  13. }
  14. }()
  15. bug1()
  16. select {}
  17. }

这里有什么最佳实践吗?

英文:

I have a program with lots of goroutines, and I want to handle the panic globally. It looks like I have to add a recovery in each of the goroutines, is there a way to do it globally?

I wrote a test program and I add a recover() in main, but it won't catch the crash in other goroutines:

  1. package main
  2. import "log"
  3. func bug2() {
  4. panic("bug2()")
  5. }
  6. func bug1() {
  7. go bug2()
  8. }
  9. func main() {
  10. defer func() {
  11. if r := recover(); r != nil {
  12. log.Println("catched")
  13. }
  14. }()
  15. bug1()
  16. select {}
  17. }

What's the best practice here?

答案1

得分: 1

golang不支持全局的recover()函数。recover()只能在当前函数或当前goroutine中执行。

第一个示例代码中,bug2()函数中使用了defer语句来捕获panic,并在recover()函数返回非nil值时打印日志。然后,在bug1()函数中启动了一个新的goroutine来调用bug2()函数。最后,在main()函数中使用sync.WaitGroup来等待goroutine执行完毕。

第二个示例代码中,bug2()函数中直接panic。然后,在bug1()函数中创建了一个新的sync.WaitGroup,并在匿名函数中使用defer语句来捕获panic,并在recover()函数返回非nil值时打印日志。在匿名函数中调用了bug2()函数,并使用sync.WaitGroup等待goroutine执行完毕。

两个示例代码的运行结果分别是:

第一个示例代码的运行结果是:

  1. 2022/09/13 11:33:33 bug2 catched

第二个示例代码的运行结果是:

  1. 2022/09/13 11:44:21 bug1 catched
英文:

golang not support global recover(). Recover() can only be executed in the current function or current goroutine.

  1. package main
  2. import (
  3. "log"
  4. "sync"
  5. )
  6. var wg sync.WaitGroup
  7. func bug2() {
  8. defer func() {
  9. if r := recover(); r != nil {
  10. log.Println("bug2 catched")
  11. }
  12. wg.Done()
  13. }()
  14. panic("bug2()")
  15. }
  16. func bug1() {
  17. go bug2()
  18. }
  19. func main() {
  20. wg.Add(1)
  21. bug1()
  22. wg.Wait()
  23. }

result:

  1. src git:(master) go run recover_global_example.go
  2. 2022/09/13 11:33:33 bug2 catched

Or:

  1. package main
  2. import (
  3. "log"
  4. "sync"
  5. )
  6. func bug2() {
  7. panic("bug2()")
  8. }
  9. func bug1() {
  10. var wg sync.WaitGroup
  11. wg.Add(1)
  12. go func() {
  13. defer func() {
  14. if r := recover(); r != nil {
  15. log.Println("bug1 catched")
  16. }
  17. wg.Done()
  18. }()
  19. bug2()
  20. }()
  21. wg.Wait()
  22. }
  23. func main() {
  24. bug1()
  25. }

retult:

  1. src git:(master) go run recover_global_example3.go
  2. 2022/09/13 11:44:21 bug1 catched

答案2

得分: 1

有没有一种全局的方法来做到这一点?

没有,不能从代码内部实现。

如果你真的需要这样(而不是修复导致程序崩溃的错误),你可以通过某种监控程序来启动你的Go程序,在出现故障时重新启动它。

英文:

> is there a way to do it globally?

No, not from inside code.

If you really need that (instead of fixing bugs that panic): Start your Go program via some monitor which restarts it in case of failure.

huangapple
  • 本文由 发表于 2022年9月13日 11:23:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/73697230.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定