🛑

Goでエラーログを出力するアンチパターンをやめる:適切なエラーハンドリング方法

2024/09/30に公開

はじめに

Go言語でエラーハンドリングをする際、多くの開発者がやってしまいがちなミスの一つが、 エラーをログに出力するだけで処理を終えること です。これにはいくつかの問題があり、最終的にシステムのデバッグや保守を困難にしてしまう可能性があります。本記事では、なぜこのようなエラーハンドリングがアンチパターンなのか、そしてより適切な方法について解説します。また、今回はGoの人気Webフレームワークである Echo を使用する例を元に説明します。

エラーハンドリングのアンチパターンとは?

エラーハンドリングにおいてよく見られるパターンが、エラーを検出した際に単にログを出力し、内部サーバーエラー(500)を返すというものです。以下はその典型的な例です。

Before: アンチパターン

if err != nil {
    log.Print(err) // 😭
    return echo.NewHTTPError(http.StatusInternalServerError)
}

このコードでは、エラーが発生した場合にその内容をログに出力し、サーバー側で問題が起きたことを示すHTTPステータス500(Internal Server Error)を返しています。この実装にはいくつかの問題があります。

問題点

  1. ログ出力だけでは情報が不足する
    • エラーが発生したことはログに残りますが、 エラーの詳細な原因や、その影響をユーザーに正しく伝える手段が不足 しています。単に500エラーを返すだけでは、クライアント側でのエラーの処理が難しくなります。
  2. エラーの種類にかかわらず同じステータスを返す
    • HTTPのエラーにはいくつかのステータスコードがあり、これを正しく使い分けることが重要です。例えば、リクエストに問題がある場合は400番台(クライアントエラー)、サーバー側の問題なら500番台(サーバーエラー)を返すべきです。単に500を返すのは、ユーザーやシステムにとって有用な情報を提供していません。
  3. 500エラーと400エラーのログの扱い
    • 500 Internal Server Errorはサーバー内部の問題を示すため、 サーバーの内部ログにのみ出力され、クライアントには詳細な情報を返しません。 一方で、400 Bad Requestのようなクライアントエラーは、サーバーのログにも残され、クライアントにも詳細なエラー情報が返されるのが一般的です。これにより、クライアントが問題の解決に役立つフィードバックを受け取ることができます。
  4. Echoフレームワークの特性
    • Goの Echoフレームワーク では、エラーハンドリングをカスタマイズできるため、クライアントに適切なエラーメッセージを返しつつ、内部ログで詳細なエラー内容を記録することが推奨されています。単にlog.Printでエラーを出力するだけではなく、エラーオブジェクトをEchoのHTTPエラーに含めることで、より豊富なエラーハンドリングが可能になります。

改善策:エラーの種類を正しく伝える

エラーハンドリングを適切に行うためには、単にログを出力するのではなく、エラーの詳細をレスポンスとして含め、かつエラーの種類に応じて正しいHTTPステータスコードを返すことが重要です。Echoフレームワークを使うことで、この改善を簡単に実現できます。

After: 改善された例

if err != nil {
    return echo.NewHTTPError(http.StatusInternalServerError).SetInternal(err)
}

この改善されたコードでは、echo.NewHTTPErrorにエラーの詳細を含め、内部サーバーエラーをクライアントに通知しつつ、サーバー内部での詳細なエラー情報を保持します。

さらなる改善: ステータスコードの使い分け

リクエストが不正な場合には、400エラーを返すべきです。こうすることで、クライアントにエラー内容を適切に伝えることができます。

if validationError {
    return echo.NewHTTPError(http.StatusBadRequest, "Invalid input")
}

if err != nil {
    return echo.NewHTTPError(http.StatusInternalServerError).SetInternal(err)
}

このように、エラーの内容に応じたHTTPステータスを返すことで、クライアントは問題を正確に理解でき、適切な対応を取ることができます。

まとめ

Goでエラーハンドリングを行う際、エラーログを出力するだけで処理を終了するのはアンチパターンです。特に、Echoフレームワークを使用している場合には、HTTPステータスコードの適切な使い分けや、クライアントとサーバーに対する正確なエラーメッセージの提供が重要です。500エラーは内部ログにのみ出力され、クライアントには情報を返しませんが、400エラーの場合は内部ログとクライアントの両方にエラーが記録されます。


このような改善を取り入れることで、アプリケーションの信頼性やデバッグのしやすさが向上します。

Discussion