猿问

如何在延迟函数Go中检测panic(nil)和正常执行?

go 运行时可以检测panic(nil)并报告错误。


但是,我无法在红色函数中检测panic(nil)with recover(),defer因为它返回nil,因此我无法将其与正常执行(没有恐慌)区分开来,因为我会测试 的返回值recover()是否为零。


例如,


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 只是一个例子,我想我可以有很多关键情况需要清理。好吧,那些清理代码也不会在真正的程序崩溃时执行,但我想尽可能地进行辩护。


无论延迟函数中的参数如何,如何检测任何恐慌?


人到中年有点甜
浏览 299回答 2
2回答

明月笑刀无情

除非我误解了您的问题,否则延迟函数调用将在恐慌时运行,即使传递的值为nil. 以下程序说明了这一点:package mainimport "fmt"func main() {    defer func() {         fmt.Println("Recover:", recover())     }()     panic(nil)}因此,您可以panic(nil)通过比较recover()to返回的值来轻松检测是否发生了nil。编辑以回答评论:是的,这是真的; 延迟调用通常会在函数返回时运行。但是它们也会在 .a 之后展开调用堆栈时运行panic()。问题更新后编辑:您是正确的,没有办法区分这些情况。另一方面,恐慌nil也没有多大意义——尤其是因为这个限制。panic(nil)我能想到的唯一用例是故意避免恢复并强制程序因堆栈跟踪而崩溃。不过,还有更优雅的方法可以做到这一点,runtime例如使用包。

白衣染霜花

我可以在退出前设置一个标志。AFAIK,panic 是特定于 goroutine 的,并且单个 goroutine 保证在单线程中。因此,不需要在 variable 周围进行同步/锁定ok。如果我错了,请纠正我。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")}
随时随地看视频慕课网APP

相关分类

Go
我要回答