[Go言語]goroutineのエラーハンドリング方法

こんにちは。KOUIKIです。

Go言語を使ったWeb開発業務に従事しています。

goroutineを使った開発業務が増えてきたので、色々と勉強中です^_^

goroutineではエラーハンドリングが特に難しいと感じます。並行して処理が走るので、どこにエラーの責任を持たせるか、というのが難しい。。。

しかし、以下の書籍で、その問題を解決するヒントを得られたので、記事にしたいと思います。

子ゴルーチンでエラーを裁く

goroutineのように並行して処理が走るプログラムを書くときは、どこにエラーを処理させる責任を持たせるかが重要だったりします。

例えば、以下のコードをみてください。

このコードでは、urlsに設定されたURLに対して、リクエストを送っています。

そして、指定されたURLが「存在しない場合」は、エラーが発生します。

このエラー処理の責任を子ゴルーチンに持たせています(main関数が実行されるとメインゴルーチンが作成され、子ゴルーチンを起動する)。

これは結構やってしまいがちなプログラミングパターンですが、あまり良い実装ではありません。

<理由>
1. 子ゴルーチンはメインゴルーチンとは別のプロセスで動いているので、エラー結果を表示させるくらいしかできない
2. 関心事(リクエスト処理とエラーハンドリング)がごっちゃになっている

以下の書籍では、このような場合の正しい解決策を提示しています。

一般的に並行プロセスはエラーを、プログラムの状態を完全に把握したいて何をすべきかをより多くの情報に基づいて決定できる別の箇所へと送るべきです。

Go言語による並行処理

解決方法

という訳で、関心毎を分けてみましょう。

今度は、エラーハンドリングをメインゴルーチンでさばきました。これにより、メインゴルーチン内で、子ゴルーチンから発生したエラーを適切に処理することができるようになりました。

ここで重要なのは、メインゴルーチンでエラーハンドリングをするべきということではありません。

取得されるであろう結果とエラーを対にする」ということが重要です。こうすることで、エラーが発生した時に処理の責任をもつゴルーチンが何をするべきなのか結果を受け取ることで決定できます。

つまり、エラーハンドリングの懸念と生産者(子ゴルーチン)を無事に切り分けることができたということです。

こうすることで、エラーハンドリングをより柔軟にすることができます。例えば、以下のようにできます。

上記では、エラーが3つ以上になったらループ処理を終了します。

かなり柔軟性があることがわかると思います!

おわりに

恥ずかしながら今までは、「どこにエラーハンドリングの責任を持たせるか」ということを考えずに、適当に実装していました。

しかし、「Go言語に夜並行処理」を読んで、新しい考え方を取り入れられた気がします。

結構オススメな書籍なので、よかったらご一読ください!

関連記事