Go でパニックをキャッチ
エラーのようなパニックは、実行時に発生します。 つまり、Go プログラムで予期しない状況が発生するとパニックが発生し、実行が終了します。
範囲外の配列アクセスなど、特定の状態が発生すると、実行時にパニックが発生する可能性があります。 これらの典型的なアクションには、制限を超えた配列のインデックス作成、型テストの実施、nil ポインターでのメソッドの実行、mutex の誤った使用、閉じたチャネルとの対話の試みなどがあります。
これらのシナリオのほとんどは、ソフトウェアのビルド中にコンパイラが検出できないプログラミング エラーから発生します。 パニックは問題を修正するための重要な情報を提供するため、開発者は頻繁にパニックを利用して、開発中に間違いを犯したことを示します。
Golang でパニックをキャッチする例をいくつか見てみましょう。
Go でパニックをキャッチ
以下のプログラムは人のフルネームを表示します。 fullName
関数は人の完全な名前を出力します。
このメソッドは、firstName
および lastName
ポインタが null かどうかを判断します。 nil
の場合、関数は適切なメッセージで panic を呼び出します。
例 1:
package main
import (
"fmt"
)
func fullName(firstName *string, lastName *string) {
if firstName == nil {
panic("runtime error: first name cannot be nil")
}
if lastName == nil {
panic("runtime error: last name cannot be nil")
}
fmt.Printf("%s %s\n", *firstName, *lastName)
fmt.Println("returned normally from fullName")
}
func main() {
firstName := "Jay"
fullName(&firstName, nil)
fmt.Println("returned normally from main")
}
出力:
panic: runtime error: last name cannot be nil
goroutine 1 [running]:
main.fullName(0x405058?, 0xc0000a2f70?)
/tmp/sandbox3339134150/prog.go:12 +0x114
main.main()
/tmp/sandbox3339134150/prog.go:20 +0x35
以下のコードは、employee
関数が main
関数から呼び出されることを示しています。 従業員の 名前
と 年齢
を入力として送信します。
従業員の年齢が定年を超えると、従業員機能はパニック モードになります。
例 2:
package main
func employee(name *string, age int) {
if age > 65 {
panic("Age cannot be greater than retirement age")
}
}
func main() {
empName := "Jay"
age := 73
employee(&empName, age)
}
出力:
panic: Age cannot be greater than retirement age
goroutine 1 [running]:
main.employee(...)
/tmp/sandbox4109873090/prog.go:5
main.main()
/tmp/sandbox4109873090/prog.go:12 +0x27
exit status 2
Go でパニックを回復する
recover
関数は、エラーの値を使用して、パニックが発生したかどうかを判断します。 パニック関数の入力は空のインターフェイスであるため、任意の型にすることができます。
空のインターフェイスを含むすべてのインターフェイス タイプは、nil
のゼロ値を持ちます。 この例に見られるように、パニックへの入力として nil
を使用しないように注意する必要があります。
例:
package main
import (
"fmt"
"log"
)
func main() {
divideByZero()
fmt.Println("Hey, we survived dividing by zero!")
}
func divideByZero() {
defer func() {
if err := recover(); err != nil {
log.Println("panic occurred:", err)
}
}()
fmt.Println(divide(1, 0))
}
func divide(a, b int) int {
if b == 0 {
panic(nil)
}
return a / b
}
出力:
Hey, we survived dividing by zero!