Go言語 – 9.エラーハンドリング
エラー処理
JavaやC++には、try, catch, throw といったエラーを処理する構文がありますが、go言語では、関数の戻り値を複数得ることができるので、errorの判定もその都度簡単に行うことができます。
例えばこんな感じ
package main import ( "fmt" "os" ) func main() { // ファイル存在確認 fname, err := fchk("testFunction07.go") if err != nil { fmt.Println(err) } else { fmt.Printf("ファイル名: %v\n", fname) } } func fchk(filepath string) (fname string, err error) { info, err := os.Stat(filepath) if err == os.ErrNotExist { fmt.Println("ファイル無し") } else if err != nil { fmt.Println("その他エラー") } else { fmt.Println("ファイル有り") fname = info.Name() } return fname, err }
エラーを無視するのも簡単です
fname, _ := fchk("testFunction07.go")
panic
ゼロ除算を行ったり、確保していない配列を参照した時等に起きる致命的なエラーが起きると強制終了しますが、この仕組みが panicです。
組み込み関数 panic を使うことで、プログラムの実行を意図して中断することができます。
package main func main() { testfunc() } func testfunc() { panic("panic!!!") } 結果... panic: panic!!! goroutine 1 [running]: main.testfunc(...) C:/@test/testfunction09.go:8 main.main() C:/@test/testfunction09.go:4 +0x40 exit status 2
recover と defer を組み合わせて、panic を拾うことができます
package main import ( "fmt" ) func main() { err := testfunc() if err != nil { fmt.Println("エラー") fmt.Println(err) } else { fmt.Println("正常") } } func testfunc() (err error) { defer func() { if rec := recover(); rec != nil { err = fmt.Errorf("recover: %v", rec) } }() testfunc1() return } func testfunc1() { fmt.Println("testfunc1 START") testfunc2() fmt.Println("testfunc1 END") } func testfunc2() { fmt.Println("testfunc2 START") testfunc3() fmt.Println("testfunc2 END") } func testfunc3() { fmt.Println("testfunc3 START") panic("panic!!!") fmt.Println("testfunc3 END") } 結果... testfunc1 START testfunc2 START testfunc3 START エラー recover: panic!!!
panic をゼロ除算に変えれば、ゼロ割りのランタイムエラーが見れます。
func testfunc3() { fmt.Println("testfunc3 START") // panic("panic!!!") var a int var b int var c int a = 10 b = 0 c = a / b fmt.Printf("c=%v\n", c) fmt.Println("testfunc3 END") } 結果... C:\@test>go run testfunction09.go testfunc1 START testfunc2 START testfunc3 START エラー recover: runtime error: integer divide by zero