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

从函数中同时返回值和错误是惯例吗

从函数中同时返回值和错误是惯例吗

Go
万千封印 2022-06-13 10:46:37
如果同时返回非零值和非零错误是否是常规的,我无法找到一个好的确认。例子:func makeHTTPCall(...) string, error {    resp, err := http.Post(...)    if err != nil {        return "", err    }    var r string    if resp.StatusCode == http.StatusOK {        if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {            return "", err        }        if err := resp.Body.Close(); err != nil {            // should I return error here even if I have successful result?            // or should I return both non-nil value and non-nil error?            // or should i just log the error?        }        return r, nil    }}绝对是编译器允许的。为什么我要问是因为约定首先检查错误。如果我返回非零值和错误,客户端代码将首先检查错误并继续错误处理路径:str, err := makeHTTPCall(...)if err != nil {   throw err}是否有任何协议?
查看完整描述

3 回答

?
拉丁的传说

TA贡献1789条经验 获得超8个赞

尽管对此的一般模式是,如果您有非零错误,则返回值是未定义的,但也有相反的众所周知的例子,例如,Reader.Read它返回一个有效数字和io.EOF一个 EOF 的情况。

另一方面,如果您同时返回非零值和错误,gRPC 库将失败。

所以,这要根据具体情况来决定。


查看完整回答
反对 回复 2022-06-13
?
慕娘9325324

TA贡献1783条经验 获得超4个赞

如果您已经确定您的函数在尝试执行的操作时完全失败,则最好为所有非错误返回值返回零值。对于选择调用您的函数并忘记检查错误的任何人,这将避免混淆或运行时错误(尽可能)。如果您的函数只产生垃圾结果,最好让调用者快速失败然后继续,直到将来某个不确定的时间点发生运行时错误。


如果您的函数部分失败,但您觉得它仍然产生了一些可用的结果,您可以返回特定的错误类型并在函数注释中记录这种情况。


鉴于上述情况,我想说您可以做以下三件事之一:


返回成功的结果以及特定的错误(您在函数注释中记录)。调用者可以先检查此错误,如下所示:


res, err := myLib.MakeHTTPCall()

if err == myLib.RequestBodyCloseErr {

   // do what you need to in case of this error

} else if err != nil {

   // general error handling

}

第二种选择是返回 "" (字符串的零值)和来自resp.Body.Close. 在这种情况下,您选择放弃该函数到目前为止所做的工作。


最后一个选项,如果您不想停止处理错误并且您不太关心它以将其返回给调用者(我假设此代码适用于您和您的团队,而不是某些公共图书馆 -如果是用于库,则前两个选项会更好 IMO。)是简单地记录错误并返回成功的结果和 nil。


您选择哪个选项将取决于您认为此错误的严重程度。这还取决于您认为此错误在生产中实际发生的可能性有多大。


查看完整回答
反对 回复 2022-06-13
?
慕标5832272

TA贡献1966条经验 获得超4个赞

一般来说,返回错误是非常标准的方式:如果返回非零错误,则所有其他值都应为 nil 或零,具体取决于类型。虽然有一个重要的例外。

在这篇博文https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully中,著名的 Go 开发者 Dave Cheney 深入介绍了哨兵错误概念。

一些错误意味着处理由于当前状态的问题而无法继续。

戴夫切尼写道:

«该名称源于计算机编程中使用特定值表示无法进行进一步处理的实践。所以对于 Go,我们使用特定的值来表示错误。»

其他答案中已经提到了最著名的哨兵错误io.EOF。标准 go 库中还有其他一些地方使用了标记错误,例如archive/zip.

在乔·博德纳 (Joe Bodner ) 的Learning Go ( pp.161-165)中有很大一部分专门讨论您的问题和标记错误,无论如何我都建议您这样做,不仅是为了详细回答您的问题。


查看完整回答
反对 回复 2022-06-13
  • 3 回答
  • 0 关注
  • 130 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信