errors
包在 Go 1.13 版本中,errors
包引入了一种新的错误处理机制,它允许我们在错误中包含更多的上下文信息。通过使用 fmt.Errorf
函数和 %w
格式化动词,我们可以创建一个新的错误,它包含一个原始错误和一个错误消息。然后,我们可以使用 errors.Is
和 errors.As
函数来检查或获取原始错误。
虽然 errors
包提供了一种基本的错误包装机制,但有时候我们可能需要传递更复杂的上下文信息。这时,我们可以创建一个自定义的错误类型。
比如,我们可以定义一个 HTTPError
类型,它包含一个 HTTP 状态码和一个内部错误:
type HTTPError struct {
StatusCode int
Err error
}
func (e *HTTPError) Error() string {
return fmt.Sprintf("status %d: %v", e.StatusCode, e.Err)
}
func (e *HTTPError) Unwrap() error {
return e.Err
}
在这个例子中,HTTPError
实现了 error
接口,因此它可以像普通错误一样使用。同时,Unwrap
方法让我们可以使用 errors.Is
和 errors.As
函数来检查或获取 HTTPError
中的原始错误。
我们可以在 REST 模块中创建一个 HTTPError
,并将其返回给调用者:
func SendCommand() error {
resp, err := http.Get("...")
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
return &HTTPError{
StatusCode: resp.StatusCode,
Err: errors.New("unexpected status code"),
}
}
return nil
}
在调用者(例如指令管理模块)中,我们可以使用 errors.As
函数来检查或获取 HTTPError
:
err := SendCommand()
if err != nil {
var httpErr *HTTPError
if errors.As(err, &httpErr) {
fmt.Printf("HTTP error with status code %d\n", httpErr.StatusCode)
} else {
fmt.Println(err)
}
}
在 Go 中,通过创建自定义的错误类型和使用 errors
包,我们可以在错误中传递丰富的上下文信息,从而更好地处理错误。当然,每种方案都有其适用的场景和限制,我们需要根据实际的需求和环境来选择最适合的方案。