【问题标题】:Generic panic recovering in go programsGo 程序中的一般恐慌恢复
【发布时间】:2019-10-07 15:40:21
【问题描述】:

我试图从我的程序中创建的 go 例程中捕获崩溃/恐慌,以便将它们发送到我的崩溃错误报告服务器(例如 Sentry/Raygun)

例如,

func main() {

    go func() {
        // Get this panic
        panic("Go routine panic")
    }()
}

The answer 表示一个 goroutine 无法从另一个 goroutine 的恐慌中恢复。

惯用的方法是什么?

【问题讨论】:

    标签: go crash-reports sentry panic raygun


    【解决方案1】:

    您必须将一些代码“注入”到作为新 goroutine 启动的函数中:您必须调用延迟函数,在该函数中调用 recover()。这是从恐慌状态中恢复的唯一方法。见相关:Why does `defer recover()` not catch panics?

    例如:

    go func() {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("Caught:", r)
            }
        }()
    
        panic("catch me")
    }()
    

    这将输出(在Go Playground 上尝试):

    Caught: catch me
    

    在您启动的每个 goroutine 中都执行此操作是不可行的,但当然您可以将恢复日志记录功能移至命名函数,然后调用它(但当然要延迟):

    func main() {
        go func() {
            defer logger()
            panic("catch me")
        }()
    
        time.Sleep(time.Second)
    }
    
    func logger() {
        if r := recover(); r != nil {
            fmt.Println("Caught:", r)
        }
    }
    

    这将输出相同的结果(在Go Playground 上尝试)。

    另一个更方便、更紧凑的解决方案是创建一个实用函数,一个接收函数并负责恢复的“包装器”。

    这就是它的样子:

    func wrap(f func()) {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("Caught:", r)
            }
        }()
    
        f()
    }
    

    现在使用起来更简单了:

    go wrap(func() {
        panic("catch me")
    })
    
    go wrap(func() {
        panic("catch me too")
    })
    

    它会输出(在Go Playground上试试):

    Caught: catch me
    Caught: catch me too
    

    最后说明:

    请注意,启动实际的 goroutine 发生在 wrap() 之外。这使调用者可以选择是否需要新的 goroutine,只需在 wrap() 调用前加上 go。通常这种方法在 Go 中是首选的。这允许您通过将任意函数传递给wrap() 来执行任意函数,并且即使您不希望在新的 goroutine 中同时运行它,它也会“保护”其执行(通过从恐慌中恢复、正确记录/报告它)。

    【讨论】:

      猜你喜欢
      • 2011-03-25
      • 2018-10-28
      • 2015-10-20
      • 2015-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-07
      相关资源
      最近更新 更多