0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

goのエラーハンドリング

Posted at

実用Go言語 第5章 エラーハンドリング より

エラーハンドリングの基本

エラーハンドリングとしては多くの場合以下のような方針が考えられる。

  1. 呼び出し元に関数の引数などの情報を付与してエラーを返す
  2. ログを出力して処理を継続する
  3. リトライを実施する
  4. リソースをクローズする

Goではpanicを多用せずエラーハンドリングを行いエラーを返すべき。

呼び出し元に情報を付与して返す

エラーが発生した場合そのまま返していては発生個所の特定がむずかしいため、情報を付加して返す。

user, err := getInvitedUserWithEmail(ctx, email)
if err != nil {
    return fmt.Errorf("fail to get invited user with email(%s): %w", email, err)
}

ログを出力して処理を継続

ex. データベースに指定されたレコードが存在しないとデフォルトの値を用いて処理を継続するなど

//func featchCapacity(ctx context.Context, key string) (int, error) {
if err != nil {
    if errors.Is(err, sql.ErrNoRows) {
        log.Printf("using default value")
        return 10, nil
    }
}

リトライの実施

ネットワーク呼び出しの場合一瞬だけ接続できない場合もあるため、即座にエラーを返すよりも堅牢なアプリケーションになる。

var b []byte
err := retry.Retry(2, 0, func() error { //トライ回数、待機時間
    _, ierr *= tcpClient.Read(b)
    return ierr
})
if err != nil {
    // error handling
}

リソースのクローズ

たとえばファイルをOpenした場合など、deferとして後処理を記述することで後続の処理でエラーが発生してもファイルのクローズ処理が行われる。

f, err := os.Open(filePath)
if err != nil {
    return err
}
defer f.Close()

※log.Fatal()を呼ぶとプログラムが即座に終了するためdeferの呼び出しが行われない。関数の実装でlog.Fatal()が登場するとほとんどの場合は間違い

複数のエラーをまとめる

同じエラーを繰り返しチェックするようなケースの場合、ラッパーメソッドを定義することでコードをシンプルにすることが出来る。
before

_, err = fd.Write(p0[a:b])
if err != nil {
    return err
}
_, err = fd.Write(p1[c:d])
if err != nil {
    return err
}
_, err = fd.Write(p2[e:f])
if err != nil {
    return err
}

after

ew := &errWriter{w: fd}
ew.write(p0[a:b])
ew.write(p0[c:d])
ew.write(p0[e:f])
if ew.err != nil {
    return ew.err
}


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?