我曾经认为,如果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开始恐慌,调用者的延迟恢复机制将无济于事。整个程序仍然无效。
所以为什么?理论上,调用者功能仍在运行。当出现紧急情况时,调用者的延迟功能应起作用(包括恢复)。
该规范说:
在执行函数F时,显式调用panic或运行时panic会终止F的执行。然后,照常执行F延迟的任何函数。接下来,运行由F的调用者运行的所有延迟函数,依此类推,直到执行goroutine中顶级函数延迟的任何函数。这时,程序终止,并报告错误情况,包括紧急情况的参数值。此终止序列称为恐慌。
因为fun2
是在goroutine中执行的顶层函数,fun2
并且无法从紧急情况中恢复,所以程序在发生fun2
紧急情况时会终止。
fun1
当goroutine执行fun2
恐慌时,不会调用延迟调用。
一个goroutine无法从另一个goroutine的恐慌中恢复过来。
我曾经认为goroutine中的恐慌会杀死程序,如果它的调用者在恐慌之前完成(延迟恢复没有任何帮助,因为在这一点上还没有恐慌发生), 直到我尝试下面的代码: 我发现无论调用方函数是否完成,如果goroutines开始恐慌,调用方的延迟恢复机制都没有帮助。整个程序还是死气沉沉的。
我正在学习围棋,我试图理解如何正确处理来自外部包的恐慌。 调用doFoo方法会使服务器崩溃,我认为这是正确的行为,因为应用程序现在处于受损状态。最好是崩溃,然后通过某个负载均衡器将后续请求转发到不同的进程。但是,我的api服务器可能还在为其他客户机服务,它可能在维护websockets,而且我可能还想在这里返回一个500错误。 来自nodejs,我习惯了处理未捕获的同步异常和处理未捕获的异步异常的
问题内容: 我需要运行一个长时间运行的子进程,并且如果我(出于任何原因)退出父应用程序而将其杀死。 这是代码: 在这里产生明显 它按预期方式工作-子进程被终止。 但这在goroutine中发生: 恐慌仍然发生,但是随后似乎没有被调用,子进程也没有被杀死。 有什么办法解决吗? 更新 我需要一个跨平台的解决方案(至少对于Linux和FreeBSD) 最小示例: 别忘了 (为简便起见,未进行错误检查):
问题内容: 我需要从被叫方获取呼叫者信息(什么文件/什么行)。我了解到可以为此目的使用inpect模块,但不能完全使用它。 如何使用inspect获取那些信息?还是有其他方法来获取信息? 问题答案: 呼叫者的帧比当前帧高一帧。您可以用来查找呼叫者的框架。然后使用inspect.getframeinfo获取调用者的文件名和行号。
我试图从我的程序中创建的go例程中捕捉崩溃/恐慌,以便将它们发送到我的崩溃错误报告服务器(如Sentry/Raygun) 例如, 做这件事的惯用方法是什么?