猿问

从恐慌中恢复的程序未按预期退出

据我了解,当恐慌恢复时,我希望程序退出并表现出正常行为,但事实并非如此。我期望最后一行打印“程序结束”是否正确?如果出现运行时错误,它不会被打印,是吗?


package main


import (

    "fmt"

)


func main() {

    defer func() {

        if r := recover(); r != nil {

            fmt.Printf("Cause of panic ==>>, %q\n", r)

        }

    }()

    f(3)

    fmt.Println("End of program")

}


func f(x int) {

    fmt.Printf("f(%d) is called.\n", x) //panic triggered when x==0

    // defer called in reverse order in case of panic

    defer fmt.Printf("defer %d\n", x+0/x)


    f(x-1)

}


蝴蝶不菲
浏览 180回答 2
2回答

侃侃尔雅

Go 规范很好地描述了panic/recover发生的事情。恐慌会终止当前函数和所有调用者,直到程序退出。在途中,它执行所有的延迟函数。如果其中一个函数有 arecover()并且干净地退出,则停止恐慌传播。在您的情况下,恐慌按以下顺序终止函数:f(0), f(1), f(2), f(3), main(), 运行每个函数的延迟函数。您的延迟函数recover()位于main(). 这意味着main()在到达 print 语句之前被恐慌中断,并且延迟函数在之后被调用。如果你想在 main 中捕捉恐慌、恢复并继续,你需要添加一个中间函数。例如:func main() {    handlePanic(3)    fmt.Println("End of program")}func handlePanic(x int) {    defer func() {        if r := recover(); r != nil {            fmt.Printf("Cause of panic ==>>, %q\n", r)        }    }()    f(x)}func f(x int) {    fmt.Printf("f(%d) is called.\n", x) //panic triggered when x==0    // defer called in reverse order in case of panic    defer fmt.Printf("defer %d\n", x+0/x)    f(x-1)}

元芳怎么了

不会打印“程序结束”。当检测到恐慌时,导致恐慌的函数立即返回,以及调用该函数的函数等,一直到调用的函数recover。当该函数返回并恢复时,程序会继续运行,就好像没有发生恐慌一样。在您的情况下,main是恢复的功能。恐慌在f(3)调用时触发,并且在 main 返回后进行恢复,绕过 println。
随时随地看视频慕课网APP

相关分类

Go
我要回答