【问题标题】:How should we handle errors when return it in go? [closed]go中return的时候应该如何处理错误呢? [关闭]
【发布时间】:2021-09-13 16:28:21
【问题描述】:

哪个更好?

1
err := MakeFood()
if err != nil{
    return err
}
2
err := MakeFood()
if err != nil{
    logs.Errorf("failed to make food, error=%v",err)
    return err
}
3
err := MakeFood()
if err != nil{
    return fmt.Errorf("failed to make food, error=%w",err)
}
4
var ErrMakeFood = errors.New("failed to make food")

err := MakeFood()
if err != nil{
    return ErrMakeFood // we discard err
}

在我的实践中,return fmt.Errorf("xxx, error=%w",err) 是我最喜欢的,它会在错误发生并返回时创建一个级联错误字符串。
但似乎,在 go builtin src 代码中,return err 是正常和整洁的。
有时我们被建议使用静态错误声明(我给出的示例 4)。这是名为 goerr113 的 golang-lint 的 lint 规则。

【问题讨论】:

  • 定义自己的错误包。
  • 做最适合您团队的事情。如果您注意到与仅返回错误而不包装错误相关的信息丢失,并对其进行扩展证明是有问题的,那么无论如何return fmt.Errorf("xxx, error=%w", err) 是更优越的选择。有时,您需要打破常规才能满足您的需求。
  • 唯一的答案是“视情况而定”。你必须做你认为最适合这种情况的方法。选项 2 是唯一在我看来客观错误的选项;通常你应该处理返回一个错误,而不是处理返回它。

标签: go error-handling


【解决方案1】:

没有一个更好,它们都是不同的,可以适用于不同的情况。

第一个,

err := MakeFood()
if err != nil{
    return err
}

当已知MakeFood 为它返回的所有错误(或包装并返回 - “冒泡”)提供自己的上下文时,是可以的;例如,它返回的任何错误都包含在“无法制作食物:”上下文中。

它也适用于不需要提供任何额外上下文的其他情况。

第二个和第三个适用于执行一些概念上单一(原子)任务的更大功能的上下文,该任务由多个步骤组成(制作食物是其中一个步骤);在这种情况下,习惯上将每个步骤报告的错误包装在同一上下文中——当调用链中的每个调用添加自己的上下文时,就会导致上下文“链接”。 例如,如果我们更大的函数处理一个送餐订单,它可能看起来像这样:

func ProcessFoodDeliveryOrder() error {
  meal, err := MakeFood()
  if err != nil {
    return fmt.Errorf("failed to process order: %w", err)
  }
  err := Deliver(meal, address)
  if err != nil {
    return fmt.Errorf("failed to process order: %w", err)
  }
  return nil
}

是否应该通过使用%w 格式化动词来使用更新的Go 工具来实际嵌套 错误——而不是仅仅提供文本(消息)上下文——这是一个开放的问题:并非所有错误都需要包装(然后由errors.Is 测试或由errors.As 处理);没有必要仅仅因为您知道它存在并且看起来很酷就使用该工具:它有其运行时成本。

错误消息的格式最好使用纯 : %s 组合 - 就像使用 fmt.Errorf("new context: %s", err) 一样,因为以这种方式更改错误会产生易于理解且易于阅读的“操作:原因”文本。顺便说一句,在The Book 中推荐。

后一种方法称为“哨兵错误”。 如果你的包的用户实际上会使用这样的错误变量是可以的——直接或通过使用errors.Is对其进行测试。
但也要考虑到断言错误的行为可能更好,而不是将它们与哨兵变量进行比较。考虑阅读this 并查看net.Error

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-07
    • 2013-05-04
    • 2013-08-17
    • 1970-01-01
    • 2015-07-18
    • 1970-01-01
    • 2016-08-27
    • 2021-01-01
    相关资源
    最近更新 更多