【问题标题】:defer func not recover延迟函数不恢复
【发布时间】:2020-02-14 23:53:32
【问题描述】:

所以,我一直在摆弄go,发现下面那个函数recover成功了

package main

import (
    "fmt"
)

func a() {  
    defer func(){
        if r := recover(); r != nil {
            fmt.Println("Recovered", r)
        }
    }()
    n := []int{5, 7, 4}
    fmt.Println(n[3])
    fmt.Println("normally returned from a")
}

func main() {  
    a()
    fmt.Println("normally returned from main")
}

但这不是

package main

import (
    "fmt"
)

func r() {  
    if r := recover(); r != nil {
        fmt.Println("Recovered", r)
    }
}

func a() {  
    defer func(){
        r()
    }()
    n := []int{5, 7, 4}
    fmt.Println(n[3])
    fmt.Println("normally returned from a")
}

func main() {  
    a()
    fmt.Println("normally returned from main")
}

谁能解释为什么?我一直在寻找答案,但没有找到任何我能完全理解的东西。 谢谢。

【问题讨论】:

    标签: go deferred recover panic


    【解决方案1】:

    只有在直接从延迟函数调用时,才会停止调用恢复。以下是来自recover documentation的相关文字:

    在延迟函数(但不是由它调用的任何函数)内执行恢复调用会通过恢复正常执行来停止恐慌序列并检索传递给恐慌调用的错误值。

    【讨论】:

    • 我还是不明白,第一个例子有效,如果我使用defer r() 它也有效。但不是像第二个例子那样,所以我只能在一个函数调用后面使用recover()?像 g() -> r() 但不是 g() -> f() -> r() ?
    • Recover 在直接调用延迟函数时恢复正常执行,但不是延迟函数调用的任何函数。 g() -> f() -> recover()的调用树在g()返回时不会恢复正常执行。
    • 应该注意a() 可以调用一个外部函数,该函数会发生恐慌 - 并且在其他一些多级深度嵌套函数调用中会发生恐慌 - 而a() 仍然可以恢复恐慌,因为它启动了调用链。
    猜你喜欢
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多