- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
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()
的“上层”调用来停止.
Suppose a function
G
defers a functionD
that callsrecover
and a panic occurs in a function on the same goroutine in whichG
is executing. When the running of deferred functions reachesD
, the return value ofD
's call torecover
will be the value passed to the call of panic. IfD
returns normally, without starting a new panic, the panicking sequence stops. In that case, the state of functions called betweenG
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/
我是一名优秀的程序员,十分优秀!