プログラムにおいて処理を続行することが不可能なエラーが発生した場合には、例外処理を行います。
例外処理は、本来実行したい処理とは異なる部分ですが、全く記述しなかったり、不適切に記述すると、エラー発生時にシステムが停止してしまったり、必要な情報を残すことができなかったりするなどの重大な事態を招いてしまう恐れがあります。
ですから、実際の開発現場でプログラミングをするには、必須の処理となります。
本記事では、Goにおける例外処理についてまとめます。
プログラミング初心者の方の学習や、忘れてしまった方の復習として、参考にしていただければ幸いです。
記載しているプログラムは、Go1.15.2を使って動作確認をしています。
Goでは例外が存在しない
まずお伝えしたいのは、Goでは、他の言語であるようなtry-catch-finally形式の例外処理機構はありません。
その理由は公式ドキュメントのFAQにも記載されています。
そのため、エラーが発生した場合に、すぐさま関数を抜けて呼び出し元に戻すようなことはできません。
その代わりとして、Goでは戻り値を複数返すことができることを利用して、エラー情報を2つ目の戻り値として返すことが推奨されています。
また、システムが復帰できないような状態になった際の手段として、panic、defer、recoverという機能も用意されています。
本記事では、システム復帰可能なエラーハンドリングを対象として、戻り値でエラー情報を返す方法を例外処理と位置づけて解説します。
Goの例外処理
Goの例外処理に関連する記述は以下のとおりです。
- 関数の戻り値でエラー情報を受け取る
- fmt.Errorf文で例外情報を作成する
関数の戻り値でエラー情報を受け取る
関数呼び出し時の2つ目の戻り値をエラー情報として受け取ります。
その戻り値がnilであれば正常、nilでなければ例外発生として処理を記述します。
func main() { fmt.Println("before error.") _, e := OccurTestError() if e != nil { fmt.Println("error.") return } fmt.Println("after error.") }
上記のmain関数では、OccurTestErrorという関数を呼び出し、そこでは必ずエラー情報が戻り値として返されるとします。
2つ目の戻り値のeをif文で評価し、エラー情報がnilでない場合は、returnして、そこで処理を終了します。
つまり、上記の例では、”before error.”が表示された後に、ifブロックに入り、”error.” が表示されて終了します。”after error.”は表示されません。
fmt.Errorf文で例外情報を作成する
fmt.Errorf文を使うことで、プログラマーは任意の場所で例外情報を作成することができます。
作成した例外情報を戻り値の最後につけます。
func OccurTestError() (string, error) { fmt.Println("before occur.") return "", fmt.Errorf("test error.") }
上記のOccurTestError関数では、1つ目の戻り値に空文字を返し、2つ目の戻り値として例外情報を返しています。
上記のプログラムでは、例題のため必ず例外情報を返していますが、通常は何らかのチェックをしてエラーの場合には例外情報を作成して返します。
fmt.Errorfは、fmt.Sprintfと同様に文字列に変数の値を埋め込むことができます。
また、fmt.Errorfによって作成される例外情報は、errorインタフェースを実装したオブジェクトとなります。
例外オブジェクト
fmt.Errorfで作成した作成したエラー情報は、別のエラー情報を含めることができます。
func OccurTestError() (string, error) { err1 := fmt.Errorf("err1") return "", fmt.Errorf("test error, %w", err1) }
上記のプログラムでは、最初のエラー情報err1を後のエラー情報に付加して、戻り値を返しています。
戻されたエラー情報を表示すると以下の内容になります。
test error, err1
例外処理は障害発生の最後の砦
プログラムは必ずと言ってよいほどエラーが発生します。
プログラム自体が完璧であったとしても、連携しているデータベースやネットワーク、OSなどあらゆるところで想定しないエラーが発生します。
プログラマーとしては、あらゆる事態を想定し、エラーが発生してもなるべく影響を少なくし、原因調査のために必要な情報を残すという点を心がける必要があります。
僕個人としては、正常系のプログラムであれば誰でも書けるが、この例外処理を無駄なく適切に書けるプログラマーが良いプログラマーであると思っています。
そして、Goでは発生したエラーを戻り値として表すことで、発生したエラーを早めに対処し、例外情報の捕捉漏れによるシステム停止がないようにするという言語思想も理解する必要があります。
今回は、Goの例外処理についてまとめました。
参考になれば幸いです。
コメント