defer
文は、関数を抜けるときに実行する処理を登録する。defer
文で登録する処理は関数またはメソッド呼び出しでなければならない。
例を示そう。
package main import "fmt" func bar() { defer fmt.Println("bar end") fmt.Println("bar start") } func foo() { defer fmt.Println("foo end") fmt.Println("foo start") bar() } func main() { foo() }
関数 foo
、bar
でそれぞれ defer
文で処理を登録している。これを実行するとこうなる。
^o^ > go run defer.go foo start bar start bar end foo end
関数を抜けるときに処理が実行されているのがわかる。
defer
文で登録した処理は、ランタイムエラーが起こっても有効だ。次の例では一番深い関数呼び出し(baz
)で panic
を起こしている。この例でも defer
文で登録された処理は実行され、その後、エラーメッセージを表示する。
package main import "fmt" func baz() { panic("oops!") } func bar() { defer fmt.Println("bar end") fmt.Println("bar start") baz() } func foo() { defer fmt.Println("foo end") fmt.Println("foo start") bar() } func main() { foo() }
^o^ > go run defer2.go foo start bar start bar end foo end panic: oops! goroutine 1 [running]: main.baz() C:/Users/takatoh/Documents/w/learning-go/defer2.go:6 +0x6b main.bar() C:/Users/takatoh/Documents/w/learning-go/defer2.go:12 +0x141 main.foo() C:/Users/takatoh/Documents/w/learning-go/defer2.go:18 +0x141 main.main() C:/Users/takatoh/Documents/w/learning-go/defer2.go:22 +0x27 exit status 2