如果另一个 goroutine 崩溃了,如何保持 goroutine 运行?

nin*_*alt 3 concurrency go goroutine

我一直在试图找到一些东西来回答这个问题,但我找不到任何谈论它的东西。

假设我在 Go 中有一个函数,如下所示:

func main() {
    // assume this wrapped in a waitgroup or something 
    // so that it doesnt exit
    go queue.ConsumeAndDoSomething()
    go api.StartServer()
}
Run Code Online (Sandbox Code Playgroud)

我这里有两个 goroutine,它们做完全不同的事情,理想情况下,如果另一个 goroutine 崩溃/恐慌,一个应该继续运行。如果队列操作失败,API 服务器应该会受到影响,反之亦然。

我不确定这是否可能(甚至推荐)。有没有一种干净的方法可以做到这一点,或者一旦 Goroutine 发生恐慌,整个程序应该退出吗?

icz*_*cza 5

您必须使用内置recover()函数从恐慌中恢复,并且必须在延迟函数中调用它。

假设您有一个可能会出现恐慌的函数:

func doPanic() {
    log.Println("about to panic")
    panic("test")
}
Run Code Online (Sandbox Code Playgroud)

创建一个辅助函数来启动一个函数作为“受保护”的 goroutine(免受恐慌):

func protect(f func()) {
    defer func() {
        if err := recover(); err != nil {
            log.Printf("Recovered: %v", err)
        }
    }()

    f()
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

func main() {
    go protect(doPanic)

    for {
        time.Sleep(time.Second)
        fmt.Println("tick")
    }
}
Run Code Online (Sandbox Code Playgroud)

该测试应用程序将输出:

2021/03/04 14:12:31 about to panic
2021/03/04 14:12:31 Recovered: test
tick
tick
tick
...
Run Code Online (Sandbox Code Playgroud)

请参阅相关问题:Genericpanicrecoveringingoprograms