手続き的に main 内で初期化→defer 後処理→メイン処理→エラー検知したら exit 1 で終了みたいなことをやりがちだけど, 意図と違う挙動になることがあるので注意が必要というやつ。
os.Exit なし版 main 関数の終了時 defer 処理が走る
package main
import "fmt"
func main(){
fmt.Println("start")
defer func() {
fmt.Println("defer")
}()
fmt.Println("end")
}
// output:
// start
// end
// defer
os.Exit あり版
package main
import (
"fmt"
"os"
)
func main(){
fmt.Println("start")
defer func() {
fmt.Println("defer")
}()
os.Exit(1)
fmt.Println("end")
}
// output:
// start
// ...
// ...
// echo $? -> 1
終了処理でよく見る err をハンドリングして log.Fatal というやつ log.Fatal も中では os.Exit してるので同じ
// Fatal is equivalent to Print() followed by a call to os.Exit(1).
func Fatal(v ...interface{}) {
std.Output(2, fmt.Sprint(v...))
os.Exit(1)
}
回避は関数を分ける必要がある
package main
import (
"fmt"
"os"
)
func main(){
run()
os.Exit(1)
}
func run() {
fmt.Println("start")
defer func() {
fmt.Println("defer")
}()
fmt.Println("end")
}
// output:
// start
// end
// defer