😺

Golangのエラーハンドリングメモ

2022/11/13に公開

はじめに

Golangのエラーハンドリングのメモを記載しております。

参考書籍

https://www.oreilly.co.jp/books/9784814400041/

Golangのエラーハンドリング

Golangは関数からerror型を返すことよってエラーハンドリングを行います。
Golaangのエラーの特徴は下記の3つ

  • 関数が期待どおり実行された場合はerrorにはnilが返される
  • うまくいかない場合は、エラーを表す値が返される。
  • 呼びだし側ではerrorの戻り値をnilと比較しすることで処理する

具体的になコードは下記のようになります。

func hoge(num1 int num2 int) (int, error) {
	if num2 == 0 {
		return 0, error.New("denominator is 0")
	}
	return num1/num2, nil
}

errorsパッケージの関数Newにエラーを示す文字列を渡して新しいエラーを生成し、その値が返されます。
関数の呼び出し先から値が返ってきたら、下記のようにif文を使ってエラー用の変数がnil以外の値になっていないかチェックをする必要があります。

func main(){
	num1, num2 := 4, 2
	retVal, err := hoge(num1, num2)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

errorはインタフェースでメソッドを一つだけ定義されています。

type error interface {
	Error() string
}

このインタフェースを実装されるのは、errorであるとみなすことができます。
Golangでは、他の言語のように例外をthrowするのではなく、エラーを返す理由は下記の二つです。

  • 例外が適切に処理されてないと予期しないクラッシュを引き起こす
  • Goのコンパイラはすべての変数が使われることを強要するため、エラーをチェックし処理するか、_を使ってエラーの無視を明示する必要があります。

Goの標準ライブラリは文字列からエラーを生成する2つの方法があります。

  • errors.Newで文字列を受け取り、errorを返す。
  • fmt.Errorfを使ってerrorを返す。この場合は、(%s, %d, %l)などのフォーマット関連を使うことができる。

errorはインタフェースなので、ロギングやエラー処理のための付加的な情報を含む独自のエラーを定義できる。例えば、エラーの一部にステータスコードを含めることもできます。

エラーのラップ

エラーがコード界して戻されるときに、付加的にあ「コンテキスト」を付け加えたい場合などがあるかと思いますが、
その際に使えるのは、Goの標準ライブラリにエラーをラップする関数fmt.Errorfを使用する。

fmt.Errof("hoge %w", err)

deferを使ったエラーのラップ

同じメッセージを使ってエラーをラップしたい際には、deferを使うと簡潔にできます。

func DoSomeThings(num1 int, val2 string) (_ string, err error) {
	defer func () {
		 if err != nil {
			 err = fmt.Errorf("do some thihgs error %w", err)
		 }
	}
	val3, err := hoge(num1)
	val4, err := hoge(num1)
	return hoge(val3, val4)
	
}

Discussion