调用者函数如何处理子 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 中的顶级函数延迟为止,此时程序将终止并报告错误情况,包括恐慌的参数值。此终止序列称为恐慌。 “
在代码中的应用
将此规范应用到我们的代码中,我们观察到:
结论
因此,了解一个 Goroutine 无法从另一个 Goroutine 的恐慌中恢复是至关重要的。如果子 Goroutine 发生恐慌,只有该 Goroutine 本身可以使用延迟/恢复机制来处理恐慌。如果子 Goroutine 没有恢复,整个程序都会终止,无论其调用者的状态如何。
以上是为什么调用函数中的延迟'恢复”不能处理子 Goroutine 中的恐慌?的详细内容。更多信息请关注PHP中文网其他相关文章!