在 defer 函数内部发生恐慌是否可以,特别是当它已经发生恐慌时?

2024年 2月 11日 76.9k 0

在 defer 函数内部发生恐慌是否可以,特别是当它已经发生恐慌时?

在defer函数内部发生恐慌时,是否会产生影响?这是一个常见的问题,尤其是在已经发生恐慌的情况下。在PHP中,defer函数用于在当前函数返回之前执行一些清理操作。当发生恐慌时,程序会立即停止执行,并且所有的defer函数都会按照后进先出的顺序执行。因此,即使在发生恐慌之后,defer函数仍然会被执行。这对于处理资源释放和错误处理等任务非常有用。无论发生了什么,defer函数始终可靠地执行,确保代码的完整性和稳定性。

问题内容

func sub(){
defer func (){
panic(2)
}()
panic(1)
}

func main(){
defer func(){
x:=recover()
println(x.(int));
}()
sub()
}

登录后复制

我尝试了这段代码,似乎第一个恐慌 panic(1) 被第二个恐慌 panic(2) “覆盖”。

但是这样做可以吗?或者调用可能会在 defer 函数内发生恐慌的 Golang 函数?

(在 C++ 中,从析构函数中抛出异常几乎是不可接受的。如果堆栈已经展开,它会终止程序。我想知道以类似方式发生恐慌在 Golang 中是否会很糟糕。)

解决方法

是的,没关系。延迟函数引起的恐慌并不是真正的新的特殊状态,它只是意味着恐慌序列不会停止。

您的示例代码也证明了它没问题,甚至 panic() 称为可以通过对 recover() 的“上”级调用来停止延迟函数。

规范:处理恐慌:

这里需要注意的一件事是,即使您在延迟函数中调用 panic(),所有其他延迟函数仍然会运行。另外,来自延迟函数的没有 recover()panic() 宁愿“包装”现有的恐慌,而不是“覆盖”它(尽管 recover() 调用确实只会返回传递给最后一次 panic() 调用)。

请参阅此示例:

func main() {
defer func() {
fmt.Println("Checkpoint 1")
panic(1)
}()
defer func() {
fmt.Println("Checkpoint 2")
panic(2)
}()
panic(999)
}

登录后复制

输出(在 Go Playground 上尝试一下):

c2e572c1c34a0369ef7​​989373914f540

即使所有延迟函数都调用 panic(),所有延迟函数都会执行,并且打印的最终恐慌序列包含传递给所有 panic() 调用的值。

如果您在延迟函数中调用 recover(),您还会在最终打印输出中获得此“已恢复”状态或信息:

defer func() {
recover()
fmt.Println("Checkpoint 1")
panic(1)
}()
defer func() {
recover()
fmt.Println("Checkpoint 2")
panic(2)
}()

登录后复制

输出(在 Go Playground 上尝试一下):

Checkpoint 2
Checkpoint 1
panic: 999 [recovered]
panic: 2 [recovered]
panic: 1
...

登录后复制

以上就是在 defer 函数内部发生恐慌是否可以,特别是当它已经发生恐慌时?的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论