一文悟透备受争议的 Go 语言错误处理
顺带说一句,err.Error() 方法是给程序员而非代码设计的,也就是说,当我们调用 Error 方法时,结果要写到文件或是打印出来,是给程序员看的。在代码里,我们不能根据 err.Error() 来做一些判断,就像上面的 main 函数里做的那样,不好。 Sentinel errors 最大的问题在于它在定义 error 和使用 error 的包之间建立了依赖关系。比如要想判断 err == io.EOF 就得引入 io 包,当然这是标准库的包,还 Ok。如果很多用户自定义的包都定义了错误,那我就要引入很多包,来判断各种错误。麻烦来了,这容易引起循环引用的问题。 因此,我们应该尽量避免 Sentinel errors,仅管标准库中有一些包这样用,但建议还是别模仿。 第二种就是 Error Types,它指的是实现了 error 接口的那些类型。它的一个重要的好处是,类型中除了 error 外,还可以附带其他字段,从而提供额外的信息,例如出错的行数等。 标准库有一个非常好的例子:
PathError 额外记录了出错时的文件路径和操作类型。 通常,使用这样的 error 类型,外层调用者需要使用类型断言来判断错误:
但是这又不可避免地在定义错误和使用错误的包之间形成依赖关系,又回到了前面的问题。 即使 Error types 比 Sentinel errors 好一些,因为它能承载更多的上下文信息,但是它仍然存在引入包依赖的问题。因此,也是不推荐的。至少,不要把 Error types 作为一个导出类型。 最后一种,Opaque errors。翻译一下,就是“黑盒 errors”,因为你能知道错误发生了,但是不能看到它内部到底是什么。 (编辑:西安站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |