Error Handling
recover: deferした関数から直接呼ばなければpanicを回復できない
recoverをヘルパー関数へ委譲すると、panicは回復されずに呼び出し元へ伝播します。
Sourcerecover.go
Go 1.22
package deferflow
func RecoverResults() (directlyRecovered bool, helperRecovered bool, panicEscaped bool) {
directlyRecovered = recoverDirectly()
func() {
defer func() {
panicEscaped = recover() != nil
}()
helperRecovered = recoverThroughHelper()
}()
return directlyRecovered, helperRecovered, panicEscaped
}
func recoverDirectly() (recovered bool) {
defer func() {
recovered = recover() != nil
}()
panic("direct recovery")
}
func recoverThroughHelper() (recovered bool) {
defer func() {
recovered = recoverFromHelper() != nil
}()
panic("indirect recovery")
}
func recoverFromHelper() any {
return recover()
}Testrecover_test.go
Go 1.22
package deferflow
import "testing"
func TestRecoverはDeferした関数から直接呼ばなければPanicを回復できない(t *testing.T) {
directlyRecovered, helperRecovered, panicEscaped := RecoverResults()
if !directlyRecovered {
t.Fatal("directlyRecovered = false, want true")
}
if helperRecovered {
t.Fatal("helperRecovered = true, want false")
}
if !panicEscaped {
t.Fatal("panicEscaped = false, want true")
}
}01Assertion
このテストで確認できること
- defer関数内で直接recoverするとpanicを回復できる
- recoverを別の関数から呼ぶとnilになり、panicは外側まで伝播する
panicを境界で変換するrecoverは、deferした無名関数の本体から直接呼びます。共通ヘルパーへ隠すと、通常の関数呼び出しに見えてもrecoverの特別な実行条件を満たせません。
OBSERVED RESULT
direct recover → true
helper recover → false
panic escapes → true