当前位置: 首页 > 知识库问答 >
问题:

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

程俊健
2023-03-14

想想一个大项目,它处理由它自己的goroutine处理的大量并发请求。碰巧代码中有一个bug,其中一个请求会因为引用为nil而引起恐慌。

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

AFAIK,对于每一个新的go例程创建,我都必须有recover()。这是防止整个程序崩溃的唯一方法吗?

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

共有1个答案

蔺霄
2023-03-14

如果您采用延迟-恢复-所有事情,我建议您投入一些时间,以确保收集到一个清晰的错误消息,并提供足够的信息,以便及时对其采取行动。

将panic消息写入stderr/stdout并不好,因为很难找到问题所在。根据我的经验,最好的方法是投入一点时间让Go程序以合理的方式处理错误。例如,来自“github.com/pkg/errors”的errors.wrap允许包装所有错误并获得堆栈跟踪。

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

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")
    }
}()
 类似资料:
  • 如何从围棋套路中出现的恐慌中恢复过来。以下是游乐场的链接:https://play.golang.org/p/lkvkuxmhjhi

  • 在Golang中,没有恢复的panic将使进程崩溃,因此我最后将以下代码片段放在每个函数的开头: 只是为了防止我的程序崩溃。现在我在想,真的是要走的路吗?因为我觉得到处放同样的代码看起来有点奇怪。 在我看来,这是Java的方式,将异常冒泡到调用函数,直到main函数成为控制异常/恐慌的更好方式。我明白这是Go的设计,但像Go一样立即崩溃进程的好处是什么?

  • 我目前正在考虑如何编写测试来检查给定的代码是否出现了恐慌?我知道Go使用来捕捉恐慌,但与Java代码不同的是,您不能真正指定在发生恐慌时应该跳过哪些代码或您有哪些代码。所以如果我有一个函数: 我真的不知道是否发生了恐慌,我们恢复了,或者函数是否根本没有恐慌。如何指定在没有恐慌的情况下跳过哪些代码,以及在出现恐慌的情况下执行哪些代码?我如何检查我们是否从恐慌中恢复过来?

  • 即使在谷歌搜索了几个小时后,我也无法找出确切的问题。我已经检查了StackOverflow本身的几个答案,但未能找出问题所在。 错误跟踪如下: 主要活动代码: 更新1:我已经做了答案中建议的所有更改,但每当我单击MainActivity中的“跳过指令”按钮时,我的应用程序仍然崩溃。此外,当我从AdminLogin活动中单击“登录”按钮时,应用程序崩溃。我该怎么办? Update2:我提到了什么是N

  • 当我在1到9之间选择一个数字并在控制台中输入一个数字时,该方法会工作并进行正确的移动。但我的问题是如何避免当我输入一个字母而不是一个数字时,程序就崩溃了。

  • 我对还很陌生。所以,请把剑给我(如果可能的话)。 我试图通过学习这里的教程从web上获取数据 在问之前,我看了很多参考资料,比如: 博客延迟,恐慌和恢复 在Goroutines中处理恐慌 how-show-i-write-goroutine 还有几个,但我想不通。 以下是你不想去游乐场的代码(原因尚不为人所知): 我将代码修改为(假设)处理goroutine中的错误,如下所示(go-playgro