首页  >  文章  >  后端开发  >  Go 如何处理子 Goroutine 中的恐慌,以及为什么不能从父 Goroutines 中恢复它们?

Go 如何处理子 Goroutine 中的恐慌,以及为什么不能从父 Goroutines 中恢复它们?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-31 05:45:02186浏览

How Does Go Handle Panics in Child Goroutines, and Why Can't They Be Recovered from the Parent?

从子协程恐慌中恢复的机制是什么?

Go 中的恐慌处理是管理运行时错误的一个关键方面。在像 goroutine 这样的多线程环境中,问题出现了:调用者函数如何有效地从子 goroutine 中发生的恐慌中恢复?

最初,看起来 goroutine 中的恐慌将不可避免地终止程序,特别是如果调用者函数在恐慌发生之前完成执行。然而,一个简单的例子证明了事实并非如此:

<code class="go">func fun1() {
  defer func() {
    if err := recover(); err != nil {
      fmt.Println("recover in func1")
    }
  }()

  go fun2()

  time.Sleep(10 * time.Second)
  fmt.Println("fun1 ended")
}

func fun2() {
  time.Sleep(5 * time.Second)
  panic("fun2 booom!")
  fmt.Println("fun2 ended")
}</code>

在这个例子中,调用者函数 fun1 推迟了从任何潜在的恐慌中恢复的调用。令人惊讶的是,即使 fun1 在 fun2 恐慌之前完成执行,程序也不会终止,并且 fun1 中的延迟恢复机制也不会激活。为什么会出现这种情况?

Go 规范给出了答案:

即将发布的 Go 规范摘录

根据规范,当发生 Panic 时在函数中,当前函数的执行被终止,并且该函数的延迟函数照常执行。随后,调用者函数的延迟函数(直到 goroutine 中的顶级函数)也被执行。 但是,如果panic发生在goroutine的顶层函数中,程序就会终止,并报告错误情况。

在上面的例子中,fun2是顶层-发生恐慌的 goroutine 中的 level 函数。由于 fun2 中没有延迟恢复机制,因此无论调用函数 fun1 中是否存在延迟恢复机制,程序都会在发生恐慌时终止。

这种行为凸显了一个基本限制:goroutines 无法恢复来自其他 goroutine 中发生的恐慌。每个goroutine都有自己独立的执行上下文,一个goroutine中的异常或错误不能被另一个goroutine处理。因此,有必要相应地处理每个 goroutine 中潜在的恐慌。

以上是Go 如何处理子 Goroutine 中的恐慌,以及为什么不能从父 Goroutines 中恢复它们?的详细内容。更多信息请关注PHP中文网其他相关文章!

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