エラー処理は、予期しない問題に遭遇してもプログラムが動作し続けられるようにするため、ソフトウェア開発において不可欠な側面です。Goでは、エラー処理はパニックとリカバーの組み合わせで実装されています。
パニックは、プログラムの実行中に異常やエラー状態を検出するために使用されます。プログラムがパニックに遭遇すると、実行を停止してクラッシュし、システムに対するそれ以上のダメージを防ぎます。パニックを起こすには、開発者はpanic()関数を使用し、エラーを説明するメッセージを渡すことができます。
func main() {
fmt.Println("Start")
panic("Something went wrong")
fmt.Println("End")
}
この例では、"Something went wrong"という文字列を指定して、panic()関数を呼び出しています。これにより、プログラムの実行が直ちに停止し、コンソールに「Something went wrong」というメッセージが出力されます。fmt.Println("End") という行は、パニックによってプログラムがすでに終了しているため、到達することはありません。
パニックから回復せずにパニックを使用することは、開発中にエラーを素早く特定しデバッグするのに便利ですが、予期しない動作を引き起こし、エラーの診断と修正が困難になるため、プロダクションコードには推奨されません。プログラムの信頼性と堅牢性を確保するためには、常に制御され予測可能な方法でエラーを処理することが推奨されています。
Goでは、recover()関数を使用してパニックから回復することができます。リカバーはGoの組み込み関数でもあり、パニックをキャッチしてプログラムの実行を継続させるために使用されます。リカバーは通常deferキーワードと組み合わせて使用します。
パニックから回復するには、deferキーワードを使用して関数を遅延させ、遅延させた関数がrecover()関数を呼び出す必要があります。main関数でパニックが発生した場合、プログラムが終了する前にdefer関数が実行され、recover()関数がパニックをキャッチしてプログラムの実行を継続させます。
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
fmt.Println("Start")
panic("Something went wrong")
fmt.Println("End")
}
この例では、deferキーワードを使用してmain()関数を遅延させ、recover()関数を呼び出す無名関数を使用して遅延関数を作成します。プログラムがpanic()関数に遭遇すると、deferキーワードと遅延関数が存在しない限り、パニックが発生し終了します。recover()関数が呼び出されると、パニックをキャッチしてコンソールにメッセージが表示されます。
Note: recover()関数はパニックに渡された値、またはパニックがなかった場合はnilを返します。if文では、recover()関数が呼び出され、その結果が変数rに代入されています。rがnilでない場合、if文の中のコードが実行されます。
このように、パニックとリカバーを組み合わせて使用することで、プログラムの実行中に発生したエラーを検知し、適切な処理を行った上でエラーを回復させることができます。
しかし、Goの開発においてこれらのパニックとリカバーを使う場面はほぼありません。次に説明していくエラーハンドリング方法を用いるのが一般的となっています。ただ、パニックやリカバーというのは必要な知識なので、この機会に覚えておいてください。