Golang – defer, panic, recoverについて

遅延実行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

コメントを残す