遅延実行defer
- Go言語のdeferキーワードは特定文章または関数を後で(deferを呼び出す関数が終わる直前)実行させます。
- 一般的にはC#、Javaのような言語でfinallyのように最後にCleanーupに使います。
package main
import "os"
func main() {
f, err := os.Open("1.txt")
if err != nil {
panic(err)
}
// main最後にファイルのclose実行
defer f.Close()
// ファイルを読み込む
bytes := make([]byte, 1024)
f.Read(bytes)
println(len(bytes))
}
- 上記はファイルをOpenしてファイルをCloseするためにdeferを使っています。
- エラーが発生しても必ずCloseされます。
panic関数
- panic()は現在の関数を即時停止するときに使います。
- panic()が実行されると現在関数内の全てのdefer関数が実行されてからリターンされます。
- このようなpanicモード実行は上位(呼び出し元)にも同じように適用されます。(コールスタック)
- 最後はプログラムエラーを出して終了されます。
package main
import "os"
func main() {
// ファイル名の誤り
openFile("Invalid.txt")
// openFile()内でpanicが実行されたら
// 以下のprintlnは実行されない
println("Done")
}
func openFile(fn string) {
f, err := os.Open(fn)
if err != nil {
panic(err)
}
defer f.Close()
}
recover関数
- Goの内装関数
- panic関数によるパニック状態から正常状態に戻すときに使います。
- 上記のpanic例ではmain関数でprintln()が実行されずにクラッシュされますが、recover関数を使うと実行されるようにできます。
package main
import (
"fmt"
"os"
)
func main() {
// ファイル名の誤り
openFile("Invalid.txt")
// recoverによって実行される。
println("Done")
}
func openFile(fn string) {
// defer関数。
// panic呼び出し時に実行される。
defer func() {
if r := recover(); r != nil {
fmt.Println("OPEN ERROR", r)
}
}()
f, err := os.Open(fn)
if err != nil {
panic(err)
}
defer f.Close()
- defer関数を使ってopenFile()が終了される時点で必ず実行されるようにしています。
- そこでrecocerするものがあるのかチェックを行い、エラーメッセージを表示しています。
参考
http://golang.site/go/article/20-Go-defer와-panic