【问题标题】:Is return nil, nil not idiomatic go?是return nil,nil不是惯用的吗?
【发布时间】:2020-11-06 21:44:05
【问题描述】:

如果我们在 GO 中有如下方法:

GetCustomer(id string) (*Customer, error)

给定 ID 的客户可能不存在于数据库中。当没有找到客户时,代码可以

return nil, nil

这在 Go 中被认为是不好的编码习惯吗?还是惯用的 Go 代码看起来像

 return nil, errCustomerNotFound

我在第二种方法中看到的问题是,您最终会检查此特定错误并单独处理它。

Go 源代码或库中是否有出现这种情况且首选其中一种方法的示例?

更新

如果return nil, nil 被认为不是惯用的。我想知道为什么在这种情况下这是真的?由于 *Customer 是一个指针,我想返回 nil 表示没有值

【问题讨论】:

  • 第三种选择是使用签名GetCustomer(id string) (c *Customer, ok bool, err error) 并使用返回return nil, false, nil。这类似于从可能存在或不存在该键的映射中获取键。
  • ...是的,return nil, nil不是惯用的 Go。
  • 让我重新表述一下:Go 标准库不会在第一个返回值中使用标记值来指示“未找到”错误。在您的第一个示例中,标记值为 nil
  • 为什么 return nil,nil 不是惯用的,特别是在这种情况下?因为它是一个指针,所以我想返回 nil 表示没有值
  • The problem I see with the second approach is that you end up checking for this specific error and handling it seperately. 使用标准错误,如 sql.ErrNotFound (或类似的)。未找到的值是客户,这是一个对记录有用的细节,在您的代码中,大多数情况下,应该有足够的上下文来确定它是客户。

标签: go error-handling idioms


【解决方案1】:

return nil, nil 在您的情况下是否惯用取决于 nil *Customer 是否有用。

如果 *Customernil 值在您的代码中是正常的、有用的值,那么返回该值且没有错误是有意义的。

nil 结构指针很少有用,但在大多数情况下,仅此一项就可以被认为是非惯用的。

遵循的规则:

每个函数都应该返回一组有用的值。

在你的情况下,你返回一个结构指针和一个错误,人们可以合理地假设其中最多一个是 nil。

使用 nil 结构指针来指示值的缺失 可以是惯用的,但不能与错误结合使用。如果你的函数只能有一个“未找到”的错误条件,你可以选择一个只返回一个值的函数,它可能是 nil,或者你可以选择返回一个表示存在而不是错误的布尔值。

但是当还包含错误时返回 nil 表示“未找到”是令人困惑的,充其量是因为它违反了principle of least astonishment

【讨论】:

  • @nmdr 出现错误表示主返回值无效,不应按预期使用,如果没有错误,在大多数情况下,将表示逆。这可能并非总是如此,但它常见的做法,以至于会称之为惯用语。我认为,大多数 Go 程序员将习惯并依赖这种常见做法,如果他们已经检查了错误nil,因此他们会被像你这样的 api 绊倒。
【解决方案2】:

如果没有达到预期的结果,应该返回错误。例如删除记录。要删除一条记录,必须先找到/检索它,做一些业务流程检查是否有,如果一切正常则删除它。如果没有找到记录或中断业务流程,则返回错误。无论如何,删除不存在的记录都是一个错误的请求。

如果请求只是检索不受限制的记录,如果没有找到则返回 nil。如果请求获取集合,如果没有找到则返回空数组/切片。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多