Go 程序中的通用恐慌恢复
在使用 Go 例程时,可能存在您想要捕获并处理崩溃或恐慌的情况它们内部发生的事件,可能用于向 Sentry 或 Raygun 等错误报告服务器报告。然而,需要注意的是,一个 Goroutine 无法从另一个 Goroutine 的恐慌中恢复。
惯用方法
处理这个问题的惯用方法是将代码注入到作为 goroutine 启动的函数。这涉及到利用一个调用recover()的延迟函数,它提供了从恐慌状态恢复的能力。
考虑以下示例:
go func() { defer func() { if r := recover(); r != nil { fmt.Println("Caught:", r) } }() panic("catch me") }()
此代码将输出相关的恐慌
虽然在您启动的每个 goroutine 中实现这种方法是不切实际的,但您可以通过定义一个命名函数来简化该过程包括恢复功能,并在您的 goroutine 中调用该函数(通过延迟调用)。
func logger() { if r := recover(); r != nil { fmt.Println("Caught:", r) } }
通过在延迟闭包中调用此函数,您可以以简洁的方式处理恐慌情况。
go func() { defer logger() panic("catch me") }()
包装器函数
为了更方便,您可以创建一个包装器将实际函数作为输入并管理紧急恢复过程的函数。此包装器函数可以按如下方式使用:
func wrap(f func()) { defer func() { if r := recover(); r != nil { fmt.Println("Caught:", r) } }() f() }
使用此包装器可以进一步简化恐慌处理过程:
go wrap(func() { panic("catch me") })
其他注意事项
提供的示例代码演示了在wrap()函数中启动goroutine的情况。这允许调用者通过在wrapp()调用之前加上go关键字来确定是否需要一个新的goroutine。然而,wrap() 函数也可用于保护作为输入传递的任意函数的执行,即使您不想在新的 goroutine 中同时运行它们。
以上是如何从 Go Goroutine 的恐慌中恢复?的详细内容。更多信息请关注PHP中文网其他相关文章!