Go言語のpanicとrecoverの活用法!テストでバグを安全に再現する方法
生徒
「Go言語でプログラムが急に止まることがあります。これってどうやってテストできますか?」
先生
「それはGo言語のpanicという機能によるものです。テストでもpanicを再現して、原因を確認することができます。」
生徒
「panicって何ですか?」
先生
「panicはプログラムの異常を知らせる仕組みです。例えばゼロで割ろうとしたときや、想定外の値が渡ったときに発生します。」
生徒
「panicを止める方法もありますか?」
先生
「はい、recoverという関数を使うと、panicで止まるのを防ぎ、安全に処理を続けることができます。」
1. panicとは?
Go言語のpanicは、プログラムの実行を中断して異常を通知する仕組みです。例えば、ゼロで割ったり、配列の範囲外にアクセスした場合にpanicが発生します。panicが起きると、その関数は終了し、呼び出し元の関数にもpanicが伝播します。
2. recoverとは?
recoverは、panicを回復するための関数です。recoverを使うと、panicでプログラムが止まるのを防ぎ、エラー処理やログ出力を行うことができます。recoverは通常、deferと組み合わせて使います。deferは関数終了時に実行される処理です。
3. panicをテストで再現する例
テストでpanicを再現する場合、testingパッケージとdefer、recoverを使います。以下は簡単な例です。
package main
import (
"testing"
)
func Divide(a, b int) int {
if b == 0 {
panic("ゼロで割ろうとしました")
}
return a / b
}
func TestDivide_Panic(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Log("panicを検知しました:", r)
}
}()
Divide(10, 0)
}
この例では、ゼロで割る操作を行い、panicを発生させています。deferとrecoverでpanicを捕まえ、テストが異常終了しないようにしています。
4. recoverを活用して安全に処理を続ける
recoverを使うことで、panicを捕まえてエラーメッセージを記録したり、代替処理を行ったりできます。例えば、次のように書くことができます。
func SafeDivide(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic発生: %v", r)
}
}()
result = Divide(a, b)
return result, nil
}
これにより、Divide関数でpanicが発生しても、SafeDivide関数内でエラーとして扱うことができ、プログラムを安全に続行できます。
5. テストでのpanic確認のポイント
panicをテストで扱うときのポイントは次の通りです。
- 必ずdeferとrecoverでpanicを捕まえる
- panicが発生する条件を明確にする
- テスト結果にpanicの内容をログとして残す
こうすることで、テストが途中で止まることなく、どの条件でpanicが発生するかを確認できます。
6. 初心者におすすめの練習方法
最初は簡単な関数でpanicを発生させ、recoverで回復する練習をしましょう。例えば、配列の範囲外アクセスやゼロ割りなど、意図的にエラーを作り、recoverで安全に処理を続ける方法を試すと理解が深まります。慣れてくると、複雑なプログラムでもpanicとrecoverを活用して、安定したコードを書くことができるようになります。