> For the complete documentation index, see [llms.txt](https://marswang.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://marswang.gitbook.io/blog/golang/golang-bian-cheng-mo-shi-cuo-wu-chu-li.md).

# Golang编程模式：错误处理

## 包装错误

开发过程中一般我们推荐包装一下错误，而不是干巴巴地把`err`给返回到上层，我们需要把一些执行的上下文加入。

通常来说，我们会使用 `fmt.Errorf()`来完成这个事，比如：

```go
if err != nil {
   return fmt.Errorf("something failed: %v", err)
}
```

另外，在Go语言的开发者中，更为普遍的做法是将错误包装在另一个错误中，同时保留原始内容：

```go
type authorizationError struct {
    operation string
    err error   // original error
}

func (e *authorizationError) Error() string {
    return fmt.Sprintf("authorization failed during %s: %v", e.operation, e.err)
}
```

当然，更好的方式是通过一种标准的访问方法，这样，我们最好使用一个接口，比如 `causer`接口中实现 `Cause()` 方法来暴露原始错误，以供进一步检查：

```go
type causer interface {
    Cause() error
}

func (e *authorizationError) Cause() error {
    return e.err
}
```

## 最佳实践

有个好消息：有一个第三方的错误库（[github.com/pkg/errors](https://github.com/pkg/errors)）帮我们实现了以上功能，而且这个库，在各种 `golang` 项目中广泛使用，所以这个基本上来说就是事实上的标准了。

列举几个常见的项目：

* [k8s.io/kubernetes](https://deps.dev/go/k8s.io%2Fkubernetes/v1.5.0-alpha.2)
* [github.com/astaxie/beego](https://deps.dev/go/github.com%2Fastaxie%2Fbeego/v1.12.3)
* [github.com/containerd/containerd](https://deps.dev/go/github.com%2Fcontainerd%2Fcontainerd/v1.5.7)
* [github.com/docker/docker](https://deps.dev/go/github.com%2Fdocker%2Fdocker/v1.13.1)
* [github.com/go-kit/kit](https://deps.dev/go/github.com%2Fgo-kit%2Fkit/v0.9.0)
* [github.com/google/cadvisor](https://deps.dev/go/github.com%2Fgoogle%2Fcadvisor/v0.47.3)
* [github.com/hashicorp/terraform](https://deps.dev/go/github.com%2Fhashicorp%2Fterraform/v0.15.3)
* [github.com/influxdata/influxdb](https://deps.dev/go/github.com%2Finfluxdata%2Finfluxdb/v1.11.1)
* [github.com/micro/go-micro/v2](https://deps.dev/go/github.com%2Fmicro%2Fgo-micro%2Fv2/v2.9.1)
* [github.com/uber-go/zap](https://deps.dev/go/github.com%2Fuber-go%2Fzap/v1.0.0-rc.1)

信息来源：<https://deps.dev/go/github.com%2Fpkg%2Ferrors/v0.9.1/dependents，有兴趣的同学可以访问查看>

代码示例如下：

```go
import "github.com/pkg/errors"

//错误包装
if err != nil {
    return errors.Wrap(err, "read failed")
}

// Cause接口
switch err := errors.Cause(err).(type) {
case *MyError:
    // handle specifically
default:
    // unknown error
}
```

## 参考文章

* <https://coolshell.cn/articles/21140.html>
