Go言語 – 9.エラーハンドリング

2019-02-02Go言語

エラー処理

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