gpt4 book ai didi

go - 在 defer 函数内部 panic 可以吗,尤其是当它已经 panic 的时候?

转载 作者:IT王子 更新时间:2023-10-29 01:27:07 30 4
gpt4 key购买 nike

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

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

我试过这段代码,似乎第一个 panic panic(1) 被第二个 panic panic(2) 简单地“覆盖”了。

但是这样做可以吗?或者调用一个可能会在 defer 函数内部 panic 的 Golang 函数?

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

最佳答案

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

你的示例代码也证明是可以的,甚至是一个panic()从延迟函数调用可以通过对 recover() 的“上层”调用来停止.

Spec: Handling panics:

Suppose a function G defers a function D that calls recover and a panic occurs in a function on the same goroutine in which G is executing. When the running of deferred functions reaches D, the return value of D's call to recover will be the value passed to the call of panic. If D returns normally, without starting a new panic, the panicking sequence stops. In that case, the state of functions called between G and the call to panic is discarded, and normal execution resumes.

这里要注意的一件事是,即使您在延迟函数中调用 panic(),所有其他延迟函数仍然会运行。同样,没有 recover() 的延迟函数中的 panic() 将宁愿“包装”现有的 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 上尝试):

Checkpoint 2
Checkpoint 1
panic: 999
panic: 2
panic: 1

goroutine 1 [running]:
panic(0xfed00, 0x1040e140)
/usr/local/go/src/runtime/panic.go:500 +0x720
main.main.func1()
/tmp/sandbox284410661/main.go:8 +0x120
panic(0xfed00, 0x1040e0fc)
/usr/local/go/src/runtime/panic.go:458 +0x8a0
main.main.func2()
/tmp/sandbox284410661/main.go:12 +0x120
panic(0xfed00, 0x1040e0f8)
/usr/local/go/src/runtime/panic.go:458 +0x8a0
main.main()
/tmp/sandbox284410661/main.go:14 +0xc0

即使所有延迟函数都调用了 panic(),所有延迟函数都会被执行,并且打印的最终 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
...

关于go - 在 defer 函数内部 panic 可以吗,尤其是当它已经 panic 的时候?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41139447/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com