本文转载自微信公众号《Golang技术分享》,作者:机器贝尔斩波。转载本文请联系Golang技术分享公众号。在公司进行代码开发,一般都会制定一套编程规范。良好的代码规范可以提高项目的可读性,提高团队开发协作的效率。具体在Go语言方面,可以参考Go官方的GoCodeReviewComments和Uber开源的uber-go/guide项目。如果你有兴趣,你可以学习它。在这篇文章中,我们关注一点:Go的错误判断。启蒙代码直接看一段代码typeMyselfErrorstruct{}func(m*MyselfError)Error()string{return"实现错误接口的Error方法"}funcsomeWork()*MyselfError{returnnil}funcmain(){varerrerrorr=一些工作()fmt。Println(err==nil)}//output:false这个例子的输出可能会让你大吃一惊?这是因为在Go中,两个nil的比较可能不相等。在Go语言类型的可比性一文中,我们说过:对于interface接口,它的比较有两个维度,即动态类型和动态值。只有类型和值相等时,接口的==比较才会为真。typeerrorinterface{Error()string}someWork函数返回的err是一个错误接口,类型为MyselfError,值为nil,显然不符合要求:只有当type和value都为nil时,才进行nil判断接口类型将是真实的。主分支代码有上面的铺垫,你应该明白我想说什么了吧?在Go中,不要使用err==nil来做逻辑判断条件。这不仅是因为使用它会导致潜在的错误。这样的代码如果交给测试的童鞋,他们也可能会喷你。你知道为什么吗?我们可以将代码分为主代码和分支代码,主代码代表正常逻辑,分支代码记录异常情况。区分两者最简单的方法是:在一个函数中,主代码离最左边只有一个tab,而分支代码则不止一个tab。在处理错误返回的函数中,我们应该首先处理错误异常。错误处理的逻辑属于分支代码,而正常的逻辑应该放在主代码上。错误示例funcbar(){varerrrrorerr=foo()iferr==nil{//程序正常代码逻辑}else{switcherr.(type){caseerr1://doerrorhandling1caseerr2://doerrorhandling2default://做一般错误处理}}}现在知道测试童鞋为什么喷你了吗?有一个词叫测试覆盖率,代表一个测试用例走过的代码行数。如果在前面加上err==nil的判断,那么这段代码对测试是不友好的。在测试的过程中,有时候我们很难人为构造错误,那么测试用例很可能只会按照err==nil下面的代码逻辑。规范示例funcmain(){varerrerrorrr=foo()iferr!=nil{switcherr.(type){caseerr1://doerrorhandling1caseerr2://doerrorhandling2default://dogeneralerrorhandling}}//程序是正常的代码逻辑}这样的代码规范可以让我们在第一次接手一个新项目,或者codereview别人的代码时,通过阅读主要代码,快速了解代码业务逻辑,而不至于陷入琐碎的case处理。总结今天的文章虽然很短,但希望能给大家带来启发。Go中err==nil不需要判断,但是对于判断异常情况,正常逻辑放在主体,异常代码放在分支。在开发团队内部建立良好的代码规范,有助于提高代码的可读性和工作协作效率。如果你还没有类似的规范,那么参考GoCodeReviewComments,uber-go/guide来完成一套?参考GoCodeReview评论:https://github.com/golang/go/wiki/CodeReviewCommentsuber-go/guide:https://github.com/uber-go/guide
