通过消除错误来消除错误处理
统计 io.Reader 读取内容的行数
改进版本:
再看一个例子:
改进
## Wrap errors
日志记录与错误无关且对调试没有帮助的信息应被视为噪音,应予以质疑。记录的原因
是因为某些东西失败了,而日志包含了答案。
• The error has been logged.
• The application is back to 100% integrity.
• The current error is not reported any longer.
• 错误要被日志记录。
• 应用程序处理错误,保证100%完整性。
• 之后不再报告当前错误。
github.com/pkg/errors
使用原则
在你的应用代码中,使用 errors.New 或者 errros. Errorf返回错误
如果调用其他包内的函数,通常简单的直接返回
如果和其他库进行协作,考虑使用于和标准库协作的时候。errors. Wrap 或者 errors.Wrapf 保存堆栈信息。同样适用于和标准库协作的时候。
- 直接返回错误,而不是每个错误产生的地方到处打日志。
在程序的顶部或者是工作的 goroutine 顶部(请求入口),使用 %+V 把堆栈详情记录。
- 使用 errors. Cause 获取 root error,再进行和 sentinel errcr 判定。
总结:
- Packages that are reusable across many projects only return root error values.
选择 wrap error 是只有 applications 可以选择应用的策略。具有最高可重用性的包只能返回根错误值。
此机制与 Go 标准库中使用的相同(kit 库的 sql.ErrNoRows)。
- If the error is not going to be handled, wrap and return up the call stack.
这是关于函数/方法调用返回的每个错误的基本问题。如果函数/方法不打算处理错误,那么用足够的上下文 wrap errors 并将其返回到调用堆栈中。例如,额外的上下文可以是使用的输入参数或失败的查询语句。确定您记录的上下文是足够多还是太多的一个好方法是检查日志并验证它们在开发期间是否为您工作。
- Once an error is handled, it is not allowed to be passed up the call stack any longer.
一旦确定函数/方法将处理错误,错误就不再是错误。如果函数/方法仍然需要发出返回,则它不能返厂错误值。它应该只返回零(比如降级处理中,你返回了降级数据,然后需要 return nil)。