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

IT小君   2022-11-12T01:11:16

我一直在努力寻找可以回答这个问题的东西,但我找不到任何可以谈论它的东西。

假设我在 Go 中有一个函数,它是这样的:

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

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

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

点击广告,支持我们为你提供更好的服务
评论(2)
IT小君

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

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

func doPanic() {
    log.Println("about to panic")
    panic("test")
}

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

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

    f()
}

并像这样使用它:

func main() {
    go protect(doPanic)

    for {
        time.Sleep(time.Second)
        fmt.Println("tick")
    }
}

此测试应用程序将输出:

2021/03/04 14:12:31 about to panic
2021/03/04 14:12:31 Recovered: test
tick
tick
tick
...

请参阅相关问题:Go 程序中的通用恐慌恢复

2022-11-12T01:11:16   回复
IT小君

recover 如果您希望其他 goroutine 不受到影响,则每个 goroutine 都必须推迟调用以从潜在的恐慌中恢复。

代替

go queue.ConsumeAndDoSomething()

你应该使用

go func(){
    defer func() {
            if r := recover(); r != nil {
                log.Error("goroutine paniqued: ", r)
            }
        }()
    queue.ConsumeAndDoSomething()
}() 
2022-11-12T01:11:16   回复