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

调用者如何从儿童Goroutine的恐慌中恢复过来

孙震博
2023-03-14

我曾经认为goroutine中的恐慌会杀死程序,如果它的调用者在恐慌之前完成(延迟恢复没有任何帮助,因为在这一点上还没有恐慌发生),

直到我尝试下面的代码:



    func fun1() {
        fmt.Println("fun1 started")
        defer func() {
            if err := recover(); err != nil {
                fmt.Println("recover in func1")
            }
        }()

        go fun2()

        time.Sleep(10 * time.Second) // wait for the boom!
        fmt.Println("fun1 ended")
    }

    func fun2() {
        fmt.Println("fun2 started")

        time.Sleep(5 * time.Second)
        panic("fun2 booom!")

        fmt.Println("fun2 ended")
    }

我发现无论调用方函数是否完成,如果goroutines开始恐慌,调用方的延迟恢复机制都没有帮助。整个程序还是死气沉沉的。

共有1个答案

施俊哲
2023-03-14

规范规定:

在执行函数F时,对panic的显式调用或运行时panic将终止F的执行。然后,由F推迟的任何函数都将照常执行。接下来,将运行由F的调用方运行的任何延迟函数,依此类推,直到执行Goroutine中的顶级函数延迟的任何函数。此时,程序终止并报告错误条件,包括panic参数的值。这种终止序列被称为恐慌。

因为fun2是在goroutine中执行的顶级函数,并且fun2不能从panic中恢复,所以当fun2发生panic时,程序将终止。

当执行fun2的goroutine发生恐慌时,不调用fun1中的延迟调用。

一个goroutine不能从另一个goroutine的恐慌中恢复过来。

 类似资料:
  • 问题内容: 我曾经认为,如果goroutine中的恐慌的调用者在恐慌之前完成,它将使其终止程序(延迟恢复没有任何帮助,因为此时还没有发生恐慌), 直到我尝试以下代码: 我发现无论调用者函数完成与否,如果goroutines开始恐慌,调用者的延迟恢复机制将无济于事。整个程序仍然无效。 所以为什么?理论上,调用者功能仍在运行。当出现紧急情况时,调用者的延迟功能应起作用(包括恢复)。 问题答案: 该规范

  • 我正在学习围棋,我试图理解如何正确处理来自外部包的恐慌。 调用doFoo方法会使服务器崩溃,我认为这是正确的行为,因为应用程序现在处于受损状态。最好是崩溃,然后通过某个负载均衡器将后续请求转发到不同的进程。但是,我的api服务器可能还在为其他客户机服务,它可能在维护websockets,而且我可能还想在这里返回一个500错误。 来自nodejs,我习惯了处理未捕获的同步异常和处理未捕获的异步异常的

  • 我试图从我的程序中创建的go例程中捕捉崩溃/恐慌,以便将它们发送到我的崩溃错误报告服务器(如Sentry/Raygun) 例如, 做这件事的惯用方法是什么?

  • 问题内容: 在defer函数中,我想查看一次恢复调用是否会产生非nil值(不恢复) 可能吗? 问题答案: 那确切的事情是不可能的。您可能只想重新恐慌,就像在其他语言中重新引发异常一样。