https://future-architect.github.io/articles/20200522/

TIG DX所属の多賀です。最近は設計をしつつ Go も触れて引き続き楽しく仕事してます。

今回は、errors package を一部利用して、エラーコードベースのエラーハンドリング処理を実装しました。また、morikuni/failure を利用した実装への書き換えも試してみています。

前提としてGoで書かれた HTTP APIサーバーに対してのエラーハンドリングについて記載します。

エラーコードベースの例外ハンドリングについてですが、アプリケーションで発生するエラーを事前にラベリングしてコード化し、コードをもとにエラーハンドリングを実施することとします。発生時の運用対応や影響について、事前に一覧で整理することで、運用負荷を下げる意味があると考えています。(補足: Futureではメッセージコードと呼称することが多いですが、一般的な命名であるエラーコードで統一します)

以下のような形で整理しています。 実際は、エラーコード別に運用アクションも合わせて整理します。

エラーコード表 (例)

エラーコードを利用した際に重要なことは、エラーコード外のエラーを発生させないことにあると考えています。エラーコード外のエラーが発生した際、何をどうしたらよいかが明文化されていないためです。エラーは、ログより発生を検知し対応するものとした際に、いかにアプリケーションから出力されるログに対して、適切にエラーコードを付与できるかが大事です。

アプリケーション側での、コンパイルレベルでの制約は難しくコードレビューでの担保もふくまれますが、以下のようにしてエラーを出力しています。

パッケージの構造としてはシンプルな以下のイメージです。

各層のerror を wrappingして handler 層に返却します。ここは愚直にやらないといけないところです。(静的解析ツールを作ってチェックする機構を用意するほうがより良いですね。)

関数の戻り値の第2引数自体を AppError 型にすることも考えられますが、標準 error インターフェイスを尊重したほうが良いとのノウハウがあるので対応しませんでした。

handler 層に集約させます。

上記の通りに実装することで、エラーコードにエラーを集約すること自体はできました。

ただ、独自エラーを定義して Wrapするところはもっと書きやすくできないか、検討の余地がありそうだと感じました。

morikuni/failure は morikuni さんが作成されたエラーハンドリング向けのライブラリです。errors package 存在前より開発されているライブラリです。

https://github.com/morikuni/failure

Package failure provides an error represented as error code and extensible error interface with wrappers.