为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
白板的微信 2022-09-12 21:17:57
我有以下代码:package mainimport (    "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)他们是我在这里错过的东西吗,围绕着去错误处理和从恐慌中恢复过来。我是新来的,所以想要一些建议。
查看完整描述

1 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

由于 panic 和 “软” 错误都是程序异常,因此应保留非 nil 错误语义。可以将错误包装在自定义类型或简单的 error 变量中,并在函数调用后进行检查。

此外,为了实际修改返回的错误,您还应该:

  • 在延迟函数文本中使用recover()

  • 使用命名的返回参数

从规范延迟声明

例如,如果延迟函数是函数文本,并且周围的函数已命名了文本范围内的结果参数,则延迟函数可以在返回结果参数之前访问和修改结果参数

package main


import (

    "errors"

    "fmt"

    "log"

)


var ErrPanicRecovered = errors.New("recovered from panic")


// named return parameters

func 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


查看完整回答
反对 回复 2022-09-12
  • 1 回答
  • 0 关注
  • 72 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号