Posted at

os.Exit()とdefer

More than 5 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()を呼ぶようにしていた。

あまり芸術的とは思わないけれど、現実的にはそんな感じかなと思った。