Go语言中recover()何时为空操作?示例B处疑惑解析
问题解答
标记B的recover()是空操作的核心原因是:recover()要捕获panic,必须在「处理panic的延迟函数执行阶段」被调用,而标记B的recover()是在延迟函数D2的主执行流程中调用的,此时当前goroutine的panic状态还未进入可被该recover()捕获的上下文。
具体拆解执行流程:
- 当
panic(2)触发后,Go按逆序执行已注册的defer:- 先执行最内层的
defer recover()(标记A):这个recover()在注册defer时就执行了,此时还未触发panic,返回nil,是空操作。 - 接着执行中间的延迟函数D2:
- D2内部先注册两个defer:
defer fmt.Print(recover())(d2_1)和defer panic(1)(d2_2)。 - 然后执行标记B的
recover():此时虽然D2是处理panic(2)的延迟函数,但这个recover()调用发生在D2的主流程中——此时Go的运行时还未将panic(2)的处理上下文绑定到这个调用上,因此recover()返回nil,是空操作。
- D2内部先注册两个defer:
- 先执行最内层的
- D2主流程执行完毕后,开始执行D2内部的defer(逆序):
- 先执行
defer panic(1)(d2_2):触发新的panic(1),此时原来的panic(2)仍未被恢复。 - 再执行
defer fmt.Print(recover())(d2_1):这个recover()在处理新panic的延迟函数执行阶段被调用,捕获到了未被恢复的原始panic(2),输出2。
- 先执行
- 最后执行最外层的延迟函数D1:
recover()捕获到panic(1),输出1。
最终输出为21,和代码注释一致。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

