在Go中处理错误

时间:2016-11-15 14:15:50

标签: go error-handling

我现在和Go一起工作了一段时间,还没有确定我如何处理错误。

即使是标准库也有许多不同的方法来处理错误(有些甚至无法检查错误而不必求助于字符串匹配)。

我最近阅读了Dave Cheney撰写的博文Inspecting Errors。这听起来像是朝着正确方向迈出的一步,但我仍然很难真正实现它。

假设我已经创建了一个包a来向第三方REST API(例如Facebook Graph)发出请求。我希望这个软件包能够公开与API相匹配的函数 - 比方说GetUser

调用GetUser可以产生许多结果:

  1. 成功
  2. 由于第三方API停止等请求失败而失败
  3. 第三方API返回错误(如未找到用户)
  4. 响应或类似失败的反序列化
  5. 在第二种情况下,断言行为错误非常有效。然而,它在区分第三和第四种情况方面做得不够。

    我目前的用例是实现我自己的REST API,它使用第一个包。在这种情况下,我希望能够分别回复{​​{1}},200 OK503 Service Unavailable400 Bad Request个回复。

    解决此问题的一般方法是什么,而不必在包500 Internal Server Error中包含返回的http响应代码或类似内容?

2 个答案:

答案 0 :(得分:4)

我要做的是定义一些“包装错误”来表示错误实际发生的位置。 E.g。

type SerializationError struct { Error error }
func (err SerializationError) Error() string { return err.Error.Error() }

type HTTPError struct { Error error }
// ...

然后在您的API客户端的代码中:

b, err := json.Marshal(v)
if err != nil {
     return nil, SerializationError{err}
}

// ...

resp, err := client.Post(url, ct, body)
if err != nil {
    return nil, HTTPError{err}
}

然后,你可以这样做:

err := client.GetUser(id)
switch err.(type) {
case SerializationError:
    // respond with 400
case HTTPError:
    // respond with 500
// etc.
}

答案 1 :(得分:0)

在使用了一段时间之后,没有更接近一个感觉恰到好处的解决方案,我正在接受这方面没有一个好的单一解决方案。

我想这可能也是Dave Cheney的含义:

  

但是,我得出结论,没有一种方法可以处理错误。

由于我仍然希望避免由于依赖性挑战而导致类型声明错误,因此我最终引入了类似于链接文章中提到的Internal() bool模式的Temporary() bool行为。

这至少允许我断言行为而不必强制导入最初创建错误的包。

这不是最合适的,但现在必须要做。

Ainar-G的answer值得一看。