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()を呼ぶようにしていた。
あまり芸術的とは思わないけれど、現実的にはそんな感じかなと思った。