首页  >  文章  >  后端开发  >  为什么调用函数中的延迟'恢复”不能处理子 Goroutine 中的恐慌?

为什么调用函数中的延迟'恢复”不能处理子 Goroutine 中的恐慌?

Susan Sarandon
Susan Sarandon原创
2024-11-03 18:06:03629浏览

Why Doesn't a Deferred `recover` in a Caller Function Handle Panics in Child Goroutines?

调用者函数如何处理子 Goroutine 中的恐慌

以前认为,如果调用者函数发生,则 Goroutine 中的恐慌会终止程序在恐慌发生之前完成。然而,最近的代码示例表明情况并非如此:

<code class="go">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")
}</code>

令人惊讶的是,无论调用者函数 (fun1) 是在子 goroutine (fun2) 中的恐慌之前还是之后完成,程序都会终止。这就提出了一个问题:为什么调用函数中的延迟恢复机制不能防止程序崩溃?

规范的解释

根据 Go 规范:

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

在代码中的应用

将此规范应用到我们的代码中,我们观察到:

  • 当 fun2 出现恐慌时,它会变成
  • 由于 fun2 没有从恐慌中恢复,程序终止。
  • fun1 中的延迟调用不会被调用,因为恐慌发生在不同的 goroutine 中。

结论

因此,了解一个 Goroutine 无法从另一个 Goroutine 的恐慌中恢复是至关重要的。如果子 Goroutine 发生恐慌,只有该 Goroutine 本身可以使用延迟/恢复机制来处理恐慌。如果子 Goroutine 没有恢复,整个程序都会终止,无论其调用者的状态如何。

以上是为什么调用函数中的延迟'恢复”不能处理子 Goroutine 中的恐慌?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn