返回接口类型错误值的函数经常使用的协定是,调用者在不首先检查错误的情况下不应事先知道此调用返回的其他值的状态。
在大多数情况下,函数返回的错误值对于调用者而言应该是不透明的。 也就是说,错误为零的测试将显示呼叫是成功还是失败,这就是您需要做的一切。

图片从这里
少数情况下,通常与与外部世界的交互(例如网络活动)相关联,要求调用者检查错误的性质,以便决定是否重复该操作。
程序包作者的一个常见要求是返回已知的公共类型错误,以便调用者可以使用类型声明并详细检查它们。 我相信这种做法会导致许多不良结果:
- 错误的开放类型增加了包API的“联系范围”。
- 新的实现应仅返回接口声明中指定的类型,即使它们不太适合。
- 将错误类型添加到代码后,必须在不中断兼容性的情况下进行更改或弃用,从而使API脆弱。
确认预期的行为,而不是错误类型
不要声称错误值是特定类型,而是声称该值实现了特定行为。
这句话与Go隐式接口的性质一致,而不是基于继承的语言的性质的[子类型]。 考虑以下示例:
func isTimeout(err error) bool { type timeout interface { Timeout() bool } te, ok := err.(timeout) return ok && te.Timeout() }
调用方可以使用isTimeout()通过实现超时接口来确定错误是否超时,然后确认错误是否超时-所有这些都不知道类型或源错误值。
通常,使用此方法可以使用向错误路径添加说明的库来包装错误。 前提是包装的错误类型还实现了包装的错误接口。
这似乎是一个无法解决的问题,但是在实践中,有很多公认的接口方法,因此Timeout()bool和Temporary()bool将涵盖广泛的用例。
总结
确认预期的行为,而不是错误类型
对于包作者
如果您的程序包产生了临时性错误,请确保您返回实现适当接口方法的错误类型。 如果包装输出错误值,请确保包装程序支持实现原始错误值的接口。
对于套餐用户
如果需要检查错误,请使用接口确认预期的行为,而不是错误的类型。 不要向软件包作者询问开放错误类型; 通过适当地指定Timeout()或Temporary()方法,要求他们将其类型与公共接口对齐。
关于作者
本文的作者Dave Cheney是Go的许多流行软件包的作者,例如https://github.com/pkg/errors和https://github.com/davecheney/httpstat 。
来自翻译
尽管原始文章的日期为2014年底,但在我看来,它并没有失去其相关性。 所描述的方法在很少的软件包中找到,而其他方法则使用通常的方法来解决错误。
欢迎对文本进行编辑以增加材料的清晰度!