カテゴリ: Go言語 更新日: 2025/12/12

Go言語のエラーハンドリング設計パターン集!現場で役立つ実践例

Go言語のエラーハンドリング設計パターン集!現場で役立つ実践例
Go言語のエラーハンドリング設計パターン集!現場で役立つ実践例

先生と生徒の会話形式で理解しよう

生徒

「Goでエラーをどう整理したらきれいに書けますか?」

先生

「Goではエラーを返す仕組みを使って、わかりやすく、再利用しやすく設計するのがポイントです。」

生徒

「具体的にはどんなパターンがありますか?」

先生

「エラー統一、ラップ(error wrapping)、共通処理への委譲などが定番になります。それぞれ見ていきましょう!」

1. エラー返却の統一パターン

1. エラー返却の統一パターン
1. エラー返却の統一パターン

Goでは、エラーは値として返す仕組みがあります。関数が失敗する可能性があるときは、戻り値の最後にerrorを置き、正常・異常で分けます。


func readConfig(path string) (string, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return "", err
    }
    return string(data), nil
}

このように、エラー処理が一貫していて読みやすい構造になります。慣れないうちは「value, err := …」の形を覚えると良いでしょう。

2. error wrapping(エラーを包む)パターン

2. error wrapping(エラーを包む)パターン
2. error wrapping(エラーを包む)パターン

処理の流れが複数段階の場合、どの段階でエラーが発生したか分かりやすくするには、エラーをラップ(包む)と良いです。Go 1.13以降はfmt.Errorf%wを使います。


func loadUser(id int) (*User, error) {
    user, err := db.Find(id)
    if err != nil {
        return nil, fmt.Errorf("ユーザー取得失敗 id=%d: %w", id, err)
    }
    return user, nil
}

このようにすると、エラーを伝えながら原因を保持でき、ログやデバッグ時に便利です。

3. 共通エラー処理を関数にまとめる

3. 共通エラー処理を関数にまとめる
3. 共通エラー処理を関数にまとめる

エラーのログ出力や把握を共通化したいときは、関数でまとめて呼ぶとコードがスッキリします。


func handleError(err error, context string) {
    log.Printf("エラー [%s]: %v", context, err)
}

func run() {
    data, err := readConfig("config.json")
    if err != nil {
        handleError(err, "設定読み込み")
        return
    }
    fmt.Println(data)
}

このパターンを使うと、どこでエラーがあっても同じ処理・ログ形式で管理できます。

4. カスタムエラー型による詳細情報の付加

4. カスタムエラー型による詳細情報の付加
4. カスタムエラー型による詳細情報の付加

より詳しい情報を伝えたいときは、自分専用のエラー型を作成し、必要情報を付加しましょう。


type MyError struct {
    Code int
    Msg  string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("[%d] %s", e.Code, e.Msg)
}

func doTask() error {
    return &MyError{Code: 42, Msg: "処理に失敗しました"}
}

起動時にif err, ok := err.(*MyError)のように型アサーションすれば、エラーの詳細な分岐処理も可能になります。

5. パターンを組み合わせた実践例

5. パターンを組み合わせた実践例
5. パターンを組み合わせた実践例

実際の現場では、上記パターンを組み合わせて使います。たとえば:


func process(id int) error {
    user, err := loadUser(id)
    if err != nil {
        return fmt.Errorf("process内 loadUserエラー: %w", err)
    }
    // 処理続行…
    return nil
}

func main() {
    if err := process(7); err != nil {
        handleError(err, "main process")
    }
}

この例では、ラップ、共通処理利用、呼び出し元での表示、すべてがまとまり、現場でよく使われる形です。

6. 次に進むためのポイント

6. 次に進むためのポイント
6. 次に進むためのポイント
  • 戻り値は「値, error」の形式で返す
  • エラー発生時は早期リターンして処理を止める
  • fmt.Errorf + %w でエラーをラップして流れを残す
  • handleError のように共通処理にまとめてログや通知を整理する
  • 必要に応じてカスタムエラー型で制御分岐を実装する

これらの基本パターンが揃っていれば、多くの実践環境で対応しやすくなります。

Go言語を基礎からスッキリ学びたい人や、 文法だけでなく「実用的な使い方」まで押さえたい人には、 定番の入門書がこちらです。

基礎からわかるGo言語をAmazonで見る

※ Amazon広告リンク

まとめ

まとめ
まとめ

Go言語のエラーハンドリングは、一見すると単純に「エラーを返すだけ」に見えますが、実際にはとても奥深い仕組みになっています。特に現場の開発では、コードの読みやすさや再利用性、そして障害時の原因追跡のしやすさが重要になるため、エラーの扱い方には一定の設計が求められます。本記事で紹介した「エラー返却の統一」「error wrapping」「共通処理化」「カスタムエラー型」「複合パターン活用」は、Go言語の開発現場で広く使われている考え方です。どれも特別なテクニックというより、Goが備えている仕組みを丁寧に組み合わせて活かす方法といえます。

特に、Goのエラーは「例外ではなく値として返す」という特徴があるため、開発者自身が「どう扱うべきか」を決める余地が大きく、その分、設計の工夫が品質に直結します。エラーの統一的な返し方を決めるだけでも読みやすさが大きく向上し、ラップを使えば処理の流れを追いやすくなり、共通処理を関数化すればメンテナンスが容易になります。また、複雑なエラーを扱う場合にはカスタムエラー型が非常に有効で、運用時のログ解析やユーザーへのメッセージ出し分けにも役立ちます。

さらに、Go言語ではエラー処理が明確にコードに表れるため、トラブルシューティングがしやすく、コードレビューでも意図を読み取りやすいメリットがあります。初心者のうちは「毎回 err を書くのが大変」と感じるかもしれませんが、慣れてくるとこの明示的なスタイルの良さがわかるはずです。実践的なプロジェクトでは、これらのエラーパターンを組み合わせて、より安全で安定した処理に仕上げていくことが求められます。

最後に、エラーハンドリングの理解を深めるための簡単なサンプルをもう一つ紹介します。これはラップと共通処理を組み合わせた小さな例ですが、日常的に使われる形です。


func readFile(path string) (string, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return "", fmt.Errorf("ファイル読み込み失敗: %w", err)
    }
    return string(data), nil
}

func main() {
    content, err := readFile("sample.txt")
    if err != nil {
        handleError(err, "main")
        return
    }
    fmt.Println("読み込み成功:", content)
}

このように、Goのエラーハンドリングはさまざまな設計パターンを組み合わせることで、より実践的で安全なコードを実装できます。エラーを恐れるのではなく、「どう設計すれば扱いやすくなるか」を考えながら進めるのがポイントです。

先生と生徒の振り返り会話

生徒

「先生、今日の内容でGoのエラーハンドリングがだいぶ理解できました!特に、エラーをラップすると原因が追いやすくなるのが印象に残っています。」

先生

「そうですね。ラップは現場でもとてもよく使われる考え方ですし、ログから原因を特定するのにも役立ちます。あと共通処理化も大事なポイントです。」

生徒

「共通化するとコードがスッキリして読みやすくなりますね。カスタムエラーも便利そうですけど、どんな場面で使うんですか?」

先生

「例えば、エラーごとにエラーコードを使い分けたいときや、ユーザーに分かりやすく伝えたいときですね。運用時のログ分析にもとても有効なんですよ。」

生徒

「なるほど…!今日は具体例が多かったので、現場でどんな風に使えるのかイメージしやすかったです。これから自分で書くときも気をつけてみます!」

先生

「はい、その調子です。エラー処理を丁寧に書けると開発者としてのレベルがぐっと上がりますから、ぜひ実践しながら身につけていきましょう。」

関連セミナーのご案内

【超入門】ゼロから始めるGo言語プログラミング:最速で「動くアプリ」を作るマンツーマン指導

「プログラミングの仕組み」が根本からわかる。Go言語でバックエンド開発の第一歩を。

本講座を受講することで、単なる文法の暗記ではなく、「プログラムがコンピュータの中でどう動いているか」という本質的な理解につながります。シンプルながら強力なGo言語(Golang)を通じて、現代のバックエンドエンジニアに求められる基礎体力を最短距離で身につけます。

具体的な開発内容と環境

【つくるもの】
ターミナル(黒い画面)上で動作する「対話型計算プログラム」や、データを整理して表示する「ミニ・ツール」をゼロから作成します。自分の書いたコードが形になる感動を体験してください。

【開発環境】
プロの現場でシェアNo.1のVisual Studio Code (VS Code)を使用します。インストールから日本語化、Go言語用の拡張機能設定まで、現場基準の環境を一緒に構築します。

この60分で得られる3つの理解

1. 環境構築の完全な理解

「なぜ動くのか」という設定の仕組みを理解し、今後の独学で詰まらない土台を作ります。

2. Go言語の基本構造(変数・型)

データの種類やメモリの概念など、他言語にも通じるプログラミングの本質を学びます。

3. 読みやすいコードの書き方

ただ動くだけでなく、誰が見ても分かりやすい「綺麗なコード」を書くための考え方を伝授します。

※本講座は、将来的にバックエンドエンジニアクラウドインフラに興味がある未経験者のためのエントリー講座です。マンツーマン形式により、あなたの理解度に合わせて進行します。

セミナー画像

初めてのGo言語を一緒に学びましょう!

関連記事:
カテゴリの一覧へ
新着記事
New1
Go言語
Go言語のwhile的なforループの使い方!条件式ループの基本を解説
New2
Go言語
Go言語プログラムの実行方法まとめ!VSCode・ターミナルでの実行手順を解説
New3
Swift
Swift意味とは?プログラミング言語・金融・鳥の違いを徹底解説
New4
Swift
Swift 戻り値の扱い方と複数戻り値の返し方|初心者でも分かる関数の基本
人気記事
No.1
Java&Spring記事人気No1
Go言語
Go言語でリダイレクト処理を行う方法(http.Redirect)を初心者向けに解説
No.2
Java&Spring記事人気No2
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.3
Java&Spring記事人気No3
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!
No.4
Java&Spring記事人気No4
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.5
Java&Spring記事人気No5
Go言語
Go言語のgo.modファイル完全ガイド!初心者でもわかる仕組みと書き方
No.6
Java&Spring記事人気No6
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.7
Java&Spring記事人気No7
Go言語
Go言語で条件式を1行で書くコツ!三項演算子の代替と短縮記法
No.8
Java&Spring記事人気No8
Kotlin
Kotlinの演算子一覧と使い方!算術・比較・論理演算子の基本を解説