Go 如何防止围棋程序在意外恐慌后崩溃?

Go 如何防止围棋程序在意外恐慌后崩溃?,go,Go,设想一个大型项目,它处理由自己的goroutine处理的大量并发请求。碰巧代码中有一个bug,其中一个请求将由于nil引用而导致恐慌 在Java、C#和许多其他语言中,这将导致异常,从而停止请求,而不会对其他正常的请求造成任何损害。在围棋中,这将使整个程序崩溃 好的,我必须为每一个新的go例程创建recover()。这是防止整个程序崩溃的唯一方法吗 更新:为每个gorouting创建添加recover()。第三方图书馆呢?如果第三方在没有安全网的情况下创建goroutines,那么似乎没有什么可

设想一个大型项目,它处理由自己的goroutine处理的大量并发请求。碰巧代码中有一个bug,其中一个请求将由于nil引用而导致恐慌

在Java、C#和许多其他语言中,这将导致异常,从而停止请求,而不会对其他正常的请求造成任何损害。在围棋中,这将使整个程序崩溃

好的,我必须为每一个新的go例程创建
recover()
。这是防止整个程序崩溃的唯一方法吗


更新:为每个gorouting创建添加
recover()。第三方图书馆呢?如果第三方在没有安全网的情况下创建goroutines,那么似乎没有什么可做的。

如果没有恢复功能,您无法处理死机,一个好的做法是使用类似中间件的函数来实现安全功能,请签出此代码段


如果您选择延迟恢复所有内容,我建议您投入一些时间,确保收集到清晰的错误消息,并提供足够的信息,以便及时采取行动

将紧急消息写入stderr/stdout并不好,因为很难找到问题所在。根据我的经验,最好的方法是投入一点时间,让你的围棋程序以合理的方式处理错误<代码>错误。例如,Wrap
from“”允许您包装所有错误并获取堆栈跟踪

恢复恐慌通常是一种必要的罪恶。就像你说的,仅仅因为一个请求引起了恐慌而使整个程序崩溃是不理想的。在大多数情况下,恢复恐慌不会反击,但程序有可能最终处于未定义的不可恢复状态,只有手动重新启动才能修复。话虽如此,我在本例中的建议是确保您的Go程序公开一种创建核心转储的方法

下面是如何在SIGQUIT被发送到Go程序时将核心转储写入stderr(例如,
kill pid-QUIT

go func(){
//根据对该问题的回答:
// https://stackoverflow.com/questions/19094099/how-to-dump-goroutine-stacktraces
信号:=接通(切换操作信号,1)
signal.Notify(sigs,syscall.SIGQUIT)
为了{

是的,差不多。请注意,您可以使用
recover()
并从那里调用
recover()
。请注意,stdlib http服务器已经为您完成了这项工作(尽管将其作为默认设置被许多人认为是一个错误)找到nil取消引用的原因是值得的,因为这很可能是一个逻辑问题。当然,但我宁愿将nil取消引用视为一个错误日志,并尽快修复它,而不会一次又一次地破坏不相关的请求。
go func() {
    // Based on answers to this stackoverflow question:
    // https://stackoverflow.com/questions/19094099/how-to-dump-goroutine-stacktraces
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGQUIT)
    for {
        <-sigs

        fmt.Fprintln(os.Stderr, "=== received SIGQUIT ===")
        fmt.Fprintln(os.Stderr, "*** goroutine dump...")

        var buf []byte
        var bufsize int
        var stacklen int

        // Create a stack buffer of 1MB and grow it to at most 100MB if
        // necessary
        for bufsize = 1e6; bufsize < 100e6; bufsize *= 2 {
            buf = make([]byte, bufsize)
            stacklen = runtime.Stack(buf, true)
            if stacklen < bufsize {
                break
            }
        }
        fmt.Fprintln(os.Stderr, string(buf[:stacklen]))
        fmt.Fprintln(os.Stderr, "*** end of dump")
    }
}()