doudi7570
2016-12-14 09:49
浏览 34
已采纳

可以在defer函数内部惊慌吗,尤其是当它已经惊慌时?

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

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

I tried this code and it seems the first panic panic(1) is simply "overwritten" by the second panic panic(2).

But is it okay to do that? Or call a Golang function that might panic inside defer function?

(In C++ it's almost never acceptable to throw exception out of a destructor. It terminates program if stack is already unwinding. I wonder if panicking in a similar manner could be bad in Golang.)

图片转代码服务由CSDN问答提供 功能建议

  func sub(){
 defer func(){
 panic(2)
}  ()
紧急(1)
} 
 
func main(){
延迟func(){
x:= recover()
 println(x。(int)); 
}()\  n sub()
} 
   
 
 

我尝试了此代码,似乎第一个恐慌 panic(1)只是被“覆盖”了 通过第二个恐慌 panic(2)

但是可以吗? 还是调用一个可能在defer函数内部恐慌的Golang函数?

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

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dongquechan4414 2016-12-14 09:56
    已采纳

    Yes, it's okay. Panicking from a deferred function is not really a new, special state, it just means that the panicking sequence will not stop.

    Your example code also proves that it's okay, and even a panic() called from a deferred function can be stopped by an "upper" level call to 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.

    One thing to note here is that even if you call panic() in a deferred function, still all the other deferred functions will run. Also a panic() without recover() from a deferred function will rather "wrap" the existing panic and not "overwrite" it (although it's true that a recover() call will only give you back the value passed to the last panic() call).

    See this example:

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

    Output (try it on the 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
    

    Even though all deferred functions call panic(), all deferred functions get executed, and the final panic sequence printed contains values passed to all panic() calls.

    If you call recover() in the deferred functions, you also get this "recovered" state or info in the final printout:

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

    Output (try it on the Go Playground):

    Checkpoint 2
    Checkpoint 1
    panic: 999 [recovered]
        panic: 2 [recovered]
        panic: 1
    ...
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题