【问题标题】:Continue execution after recovered panic without knowing which function might panic在恢复恐慌后继续执行,而不知道哪个函数可能会恐慌
【发布时间】:2022-06-27 15:12:45
【问题描述】:

我被提到了这个问题:Program recovered from panic does not exit as expected 它工作得很好,但它依赖于知道恐慌发生在哪里才能放置延迟函数。 我的代码如下。

package main

import "fmt"

func main() {
    defer recoverPanic()
    f1()
    f2()
    f3()
}

func f1() {
    fmt.Println("f1")
}

func f2() {
    defer f3() //<--- don't want to defer f3 here because I might not know f2 will panic, panic could occuer elsewhere
    fmt.Println("f2")
    panic("f2")
}

func f3() {
    fmt.Println("f3")
}

func recoverPanic() {
    if r := recover(); r != nil {
        fmt.Printf("Cause of panic ==>> %q\n", r)
    }
}

在恐慌函数中使用延迟函数调用 f3() 可以工作,输出如下。

f1
f2
f3
Cause of panic ==>> "f2"

如果您的应用程序不知道发生恐慌的位置怎么办,我是否需要在每个可能发生恐慌的函数中添加延迟? 注释掉 defer f3() 会给我以下输出。

f1
f2
Cause of panic ==>> "f2"

f3 从不运行。

我的问题是如何在不延迟函数调用的情况下继续执行程序可能恐慌?

【问题讨论】:

    标签: go recover panic


    【解决方案1】:

    恐慌后您无法恢复函数执行。当当前执行行时使用panic无法正确继续.在恐慌之后任意恢复执行(如果可能的话)会立即乞求另一个恐慌,因为状态已经不正确并且仅仅向前冲不会解决这个问题。

    例如,假设一个函数在尝试读取切片的边界时发生恐慌。怎么可能继续?继续下去意味着什么?它应该只读取越界内存位置并获取垃圾数据吗?继续零值?从切片中获取不同的值?

    您必须处理错误情况;或者通过明确的恢复或抢先检查/纠正会导致恐慌的情况。至少在标准库中,可能引发恐慌的函数会在其文档中这样说,并解释哪些条件会导致恐慌。

    如果您通常需要安全地拨打电话空白函数并从任何恐慌中恢复,您可以为此制作一个简单的包装函数。

    func try(f func()) {
        defer func() {
            if err := recover(); err != nil {
                fmt.Println("caught panic:", err)
            }
        }()
        f()
    }
    

    然后

    func main() {
        try(f1)
        try(f2)
        try(f3)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 2021-09-15
      • 2018-09-14
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      • 2023-02-04
      相关资源
      最近更新 更多