Go语言Panic抑制与链式规则总结的正确性验证问询
Go语言Panic的抑制与链式触发分析
测试代码
package main import ( "fmt" "github.com/stretchr/testify/assert" "testing" ) // panic suppress, func ExamplePanicSuppressed() { defer func() { fmt.Printf("%s: %v\n", "A", recover()) // catch panic(2) }() defer func() { panic(2) // suppress panic(1), }() panic(1) // Output: // A: 2 } // panic chain - recover all, func ExamplePanicChain_nestedRecoverAll() { defer func() { fmt.Printf("%s: %v\n", "A", recover()) // catch panic(1) }() defer func() { defer func() { fmt.Printf("%s: %v\n", "B", recover()) // catch panic(2) }() panic(2) }() panic(1) // Output: // B: 2 // A: 1 } // panic chain - recover partly, func TestPanicChain_recoverPartly(t *testing.T) { f := func() { defer func() { defer func() { fmt.Printf("%s: %v\n", "B", recover()) // catch panic(2) }() panic(2) }() panic(1) // won't catch, will panic, } assert.Panics(t, f) // panic(1) will panic, thus true, }
初步总结与修正
你的初步总结方向正确,但可以更精准地描述:
修正后的结论
- Panic抑制:当在处理原有panic的延迟函数中触发新panic,且这个新panic未被当前延迟函数内的recover捕获时,原有panic会被丢弃,程序最终传播新panic(即新panic覆盖旧panic)。
- Panic链式触发:当在处理原有panic的延迟函数中触发新panic,且这个新panic被当前延迟函数内嵌套的延迟函数中的recover捕获时,新panic会被处理,之后原有panic的传播流程会继续执行,最终原有panic可被外层的recover捕获(即新旧panic都被处理,形成链式触发)。
详细解释
- ExamplePanicSuppressed 示例:程序先触发
panic(1),按defer后进先出顺序执行内层defer函数,该函数触发panic(2)且未做recover处理,此时原有panic(1)被丢弃,外层defer的recover最终捕获到panic(2),输出A: 2。 - ExamplePanicChain_nestedRecoverAll 示例:
panic(1)触发后,执行内层defer函数,该函数内的嵌套defer先注册,随后触发panic(2),嵌套defer的recover捕获panic(2)并输出B: 2;内层defer执行完毕后,回到原有panic(1)的处理流程,外层defer的recover捕获panic(1)并输出A: 1。 - TestPanicChain_recoverPartly 示例:
panic(1)触发后,内层defer函数触发panic(2),嵌套defer的recover捕获panic(2)输出B: 2;但原有panic(1)始终未被任何recover处理,因此程序最终会抛出panic(1),assert.Panics断言成立。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

