Go
golang

os.Exit()とdefer

More than 3 years have passed since last update.

golangのos packageにはExit()という関数がいて、その名の通りOSに値を返してプロセスが死ねる。
で、ドキュメントによると、

func Exit(code int)
Exit causes the current program to exit with the given status code. Conventionally, code zero indicates success, non-zero an error. The program terminates immediately; deferred functions are not run.

とあって、deferに登録した関数をすべて破棄してくれるらしいと書いてある。念の為に試しておくと、

package main

import "os"

func test() { println("hello in test()") }

func main() {
        println("hello in main()")
        defer test()

        os.Exit(0)
}

を実行すると

% go run test4.go
hello in main()

のようになり、ホントにdeferは実行されていない。

で、世間的にはこの性質にどう立ち向かっているかを調べるため、golangのgofmtの実装を調べた。
そのところ、

var exitCode = 0

func main() {
        // call gofmtMain in a separate function
        // so that it can use defer and have them
        // run before the exit.
        gofmtMain()
        os.Exit(exitCode)
}

func gofmtMain() {
        // 終了するタイミングで
        exitCode = 2
        return
}

という感じで、エントリポイントには一切の処理を書かないようにして、ここでos.Exit()を呼ぶようにしていた。
あまり芸術的とは思わないけれど、現実的にはそんな感じかなと思った。