区分带恢复的死机和未发生错误

我有以下代码:


package main


import (

    "fmt"

)


func recoverFoo() {

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

        println("Recovered")

    }

}

func foo() (int, error) {

    defer recoverFoo()

    panic("shit!")

}

func main() {

    x, err := foo()

    println("after foo x = " + fmt.Sprint(x))


    if err != nil {

        println("An error occured")

    } else {

        println("No error occured")

    }

}

在这种情况下,我调用 foo(实际上我的函数 foo 正在调用第三方库,该库有时会引起恐慌,但有时还会返回错误)。如果它恐慌,我不能让它崩溃应用程序,但我需要知道出了什么问题,因为我必须错误地写入本地存储。


在这种情况下,从 Foo 返回的值可以具有 0 的有效值。因此,恢复设置x和err为默认值(0和nil)不会告诉我是否确实发生了错误...x


我看到两种可能的解决方案,(1)我将err和x包装成自定义返回类型,并假设如果它为nil,则会发生错误。(2)我有第三个返回布尔值,指定没有发生恐慌(它将默认为false)


他们是我在这里错过的东西吗,围绕着去错误处理和从恐慌中恢复过来。我是新来的,所以想要一些建议。


白板的微信
浏览 73回答 1
1回答

拉风的咖菲猫

由于 panic 和 “软” 错误都是程序异常,因此应保留非 nil 错误语义。可以将错误包装在自定义类型或简单的 error 变量中,并在函数调用后进行检查。此外,为了实际修改返回的错误,您还应该:在延迟函数文本中使用recover()使用命名的返回参数从规范延迟声明:例如,如果延迟函数是函数文本,并且周围的函数已命名了文本范围内的结果参数,则延迟函数可以在返回结果参数之前访问和修改结果参数package mainimport (    "errors"    "fmt"    "log")var ErrPanicRecovered = errors.New("recovered from panic")// named return parametersfunc recoverableFoo() (i int, err error) {    defer func() {        if r := recover(); r != nil {            err = fmt.Errorf("%w: %v", ErrPanicRecovered, r)        }    }()    // panic("problem!") // or any call that may panic; uncomment to test    return 1, nil}func main() {    x, err := foo()    if err != nil {        if errors.Is(err, ErrPanicRecovered) {            log.Fatal("panicked: ", err)        }        log.Printf("some other error: %s", err.Error())        return    }    fmt.Println("after foo x = " + fmt.Sprint(x))}特别是,使用fmt。带有格式设置谓词的 Errorf 允许您正确包装错误,并在以后检查错误。是:%w如果格式说明符包含带有错误操作数的谓词,则返回的错误将实现返回操作数的 Unwrap 方法。%w游乐场: https://play.golang.org/p/p-JI1B0cw3x
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go