How to exit a go program honoring deferred calls?

前端 未结 4 387
执笔经年
执笔经年 2021-01-30 04:10

I need to use defer to free allocations manually created using C library, but I also need to os.Exit with non 0 status at some point. The

4条回答
  •  太阳男子
    2021-01-30 04:36

    After some research, refer to this this, I found an alternative that:

    • Doesn't impose a certain architecture like in https://stackoverflow.com/a/27629493/438563
    • Doesn't require any global value like in https://stackoverflow.com/a/24601700/438563

    We can take advantage of panic and recover. It turns out that panic, by nature, will honor defer calls but will also always exit with non 0 status code and dump a stack trace. The trick is that we can override last aspect of panic behavior with:

    package main
    
    import "fmt"
    import "os"
    
    type Exit struct{ Code int }
    
    // exit code handler
    func handleExit() {
        if e := recover(); e != nil {
            if exit, ok := e.(Exit); ok == true {
                os.Exit(exit.Code)
            }
            panic(e) // not an Exit, bubble up
        }
    }
    

    Now, to exit a program at any point and still preserve any declared defer instruction we just need to emit an Exit type:

    func main() {
        defer handleExit() // plug the exit handler
        defer fmt.Println("cleaning...")
        panic(Exit{3}) // 3 is the exit code
    }
    

    It doesn't require any refactoring apart from plugging a line inside func main:

    func main() {
        defer handleExit()
        // ready to go
    }
    

    This scales pretty well with larger code bases so I'll leave it available for scrutinization. Hope it helps.

    Playground: http://play.golang.org/p/4tyWwhcX0-

提交回复
热议问题