The go runtime can detect panic(nil)
and reports an error.
However, I can't detect panic(nil)
with recover()
in a defer
red function because it returns nil
, so I cannot differentiate it from normal execution (no panic) as I would test for
the return value of recover()
to be nil.
For example,
defer func(){
var err = recover()
if err != nil {
// Real serious situation. Panic from inner code.
// And we may have some critical resources which
// must be cleaned-up at any cases.
// However, this will not be executed for panic(nil)
rollback()
// I am still not sure that how should I treat `panic`…
// Should I just ignore them?
}
}()
var err = doTransaction()
if err == nil {
commit() // Happy case.
} else {
rollback() // Regular execution. Just a lucky case.
}
ROLLBACK is just an example, and I think I can have plenty of critical cases needs cleanup. Well, those cleanup code won't be executed on real program crash too, but I want to defend as much as possible.
How can I detect any panic regardless of its parameter in a deferred function?
I simply can set a flag before exit.
AFAIK, panic is goroutine-specific, and single goroutine is guaranteed to be in single thread. So synchronization/locking is not required around variable ok
. If I'm wrong, please correct me.
func clean(ok *bool) {
if *ok {
log.Printf("Execution OK. No panic detected.\n")
} else {
var reason = recover()
log.Printf("Some bad thing happen. reason = %v\n", reason)
panic("Abnormal exit. Program abandoned. Stack-trace here.")
debug.PrintStack() // Oops. this will not run.
}
}
func main() {
var ok bool = false
defer clean(&ok)
panic(nil)
test1() // Here's the main job.
ok = true
log.Printf("All work done. Quit gracefully.\n")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With