Golang是否支持全局恢复?

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

Does golang support global recovery?

问题

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

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

package main

import "log"

func bug2() {
	panic("bug2()")
}

func bug1() {
	go bug2()
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			log.Println("catched")
		}
	}()

	bug1()
	select {}
}

这里有什么最佳实践吗?

英文:

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:

package main

import "log"

func bug2() {
	panic("bug2()")
}

func bug1() {
	go bug2()
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			log.Println("catched")
		}
	}()

	bug1()
	select {}
}

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执行完毕。

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

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

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

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

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.

package main

import (
	"log"
	"sync"
)

var wg sync.WaitGroup

func bug2() {
	defer func() {
		if r := recover(); r != nil {
			log.Println("bug2 catched")
		}
		wg.Done()
	}()

	panic("bug2()")
}

func bug1() {
	go bug2()
}

func main() {

	wg.Add(1)
	bug1()

	wg.Wait()
}

result:

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

Or:

package main

import (
	"log"
	"sync"
)

func bug2() {
	panic("bug2()")
}

func bug1() {
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer func() {
			if r := recover(); r != nil {
				log.Println("bug1 catched")
			}
			wg.Done()
		}()
		bug2()
	}()
	wg.Wait()
}

func main() {
	bug1()
}

retult:

➜  src git:(master) ✗ go run recover_global_example3.go
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:

确定