我可以从恐慌中恢复过来,处理错误,然后再次恐慌并保留原始堆栈跟踪吗?
Can I recover from panic, handle the error, then panic again and keep the original stack trace?
是否可以 "rethrow" 来自 recover
的错误并保留原始堆栈跟踪?我所知道的最好的办法就是再次恐慌,但这确实会创建一个新的堆栈跟踪。
func do() {
defer func() {
cleanUp()
if x := recover(); x != nil {
handleError()
panic(x)
}
}()
doStuff()
}
我想要这个的动机是,除非我的函数正常退出或 handleError
运行,否则我的程序会死锁。除非我保留原始的 strack trace,否则我不知道它在哪里崩溃了。
堆栈中更高层的延迟函数将 运行 恐慌,即使它们不调用 recover()
。
只需删除 if-statement 和 re-panic。然后处理你的错误,让恐慌在堆栈中继续。
func do() {
defer handleError()
doStuff()
}
一个简单的演示:
https://play.golang.org/p/UiRou5MhUR
func a() {
defer func() {
fmt.Println("a")
}()
panic("test")
}
func b() {
defer func() {
fmt.Println("b")
}()
}
func main() {
fmt.Println("Hello, playground")
b()
}
产出
Hello, playground
b
解决方案是不调用 recover
,因为这样既无法重新抛出也无法访问堆栈跟踪。使用 bool 标志而不是 recover
来检查恐慌。
https://play.golang.org/p/PKeP9s-3tF
func do() {
panicked := true
defer func() {
cleanUp()
if panicked {
handleError()
}
}()
doStuff()
panicked = false
}
作为
我认为您不需要担心调用 panic 和传入 recover() 的响应对象会创建神秘的或“新的”堆栈跟踪,至少在 go 1.17 中是这样。看起来这样做只是将另一个“src/runtime/panic.go:”帧添加到跟踪中。
看这个例子测试:
https://goplay.space/#5i1RCJyiFJr
Go 不像其他语言那样对待 panic try/catch/throw/finally.
是否可以 "rethrow" 来自 recover
的错误并保留原始堆栈跟踪?我所知道的最好的办法就是再次恐慌,但这确实会创建一个新的堆栈跟踪。
func do() {
defer func() {
cleanUp()
if x := recover(); x != nil {
handleError()
panic(x)
}
}()
doStuff()
}
我想要这个的动机是,除非我的函数正常退出或 handleError
运行,否则我的程序会死锁。除非我保留原始的 strack trace,否则我不知道它在哪里崩溃了。
堆栈中更高层的延迟函数将 运行 恐慌,即使它们不调用 recover()
。
只需删除 if-statement 和 re-panic。然后处理你的错误,让恐慌在堆栈中继续。
func do() {
defer handleError()
doStuff()
}
一个简单的演示:
https://play.golang.org/p/UiRou5MhUR
func a() {
defer func() {
fmt.Println("a")
}()
panic("test")
}
func b() {
defer func() {
fmt.Println("b")
}()
}
func main() {
fmt.Println("Hello, playground")
b()
}
产出
Hello, playground
b
解决方案是不调用 recover
,因为这样既无法重新抛出也无法访问堆栈跟踪。使用 bool 标志而不是 recover
来检查恐慌。
https://play.golang.org/p/PKeP9s-3tF
func do() {
panicked := true
defer func() {
cleanUp()
if panicked {
handleError()
}
}()
doStuff()
panicked = false
}
作为
我认为您不需要担心调用 panic 和传入 recover() 的响应对象会创建神秘的或“新的”堆栈跟踪,至少在 go 1.17 中是这样。看起来这样做只是将另一个“src/runtime/panic.go:
看这个例子测试: https://goplay.space/#5i1RCJyiFJr
Go 不像其他语言那样对待 panic try/catch/throw/finally.