recover()
我理解关于Go 中的行为
的以下观点。recover()
遵循立即评估 但 延迟执行。
因此,如果它没有在延迟函数(代码片段 1)中调用,那么recover()
就会在当时对其进行评估,此时它仍然处于静止状态nil
,因此我们的代码会出现混乱。
如果它在延迟函数内部被调用,那么该函数调用会被注册,但 在发生之后recover()
才会被调用,并且我们会成功恢复。panic
package main
import "fmt"
func main() {
defer recover() // since not called inside a deferred func, it will not recover successfully
panic("This is a panic")
}
考虑到这一点,我编写了下面的代码。
import (
"fmt"
)
func main() {
defer func(){
customRecover()
}()
panic("This is a panic")
}
func customRecover(){
if r:= recover(); r!= nil{
fmt.Println("Custom Recovery for: ",r)
}
}
我在网上搜索了原因,得到了同样的答案
如果满足以下任一条件,则 recovery 的返回值为 nil:
- panic 的参数为 nil;
- goroutine 没有发生恐慌;
- 延迟函数没有直接调用恢复。
但我不明白为什么第二个片段不起作用?!?
严格来说,它满足所有 3 个条件。我是否遗漏了什么注意事项?我猜想第 3 个条件不满足,因为它不是直接调用的,而是通过嵌套函数调用调用的。但为什么它只需要在 deferred 内部呢?
正如您所说,第三个条件不满足。恢复在嵌套函数中不起作用,因为它
panic
通过调用堆栈“向下”传播,而在第二个代码片段中,从恐慌的角度来看,函数recover()
中的调用customRecover
是“向上”的,因此它“看不到”恐慌。