且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Go语言 关于go error处理风格的一些讨论和个人观点(上)

更新时间:2022-09-05 21:47:16

原创文章。转载请注明出处:server非业余研究-sunface

 

近期看谷歌go group里面有非常多讨论go error处理风格的问题,颇有启示。如今跟大家分享一下。首先请看一个提问:

Hi folks,


When I look at a lot of go code, I see the following pattern:
//当我看了很多go代码后,我发现了下面模式

x, err := foo()
if err != nil {
return err
}

y, err := bar(x)
if err != nil {
return err
}

z, err := baz(y)
if err != nil {
return err
}

// do something w/ z

return nil

This is cool, but comes off as a bit verbose. I've been using the following as a replacement, which I think is a bit nicer:
//上段代码非常cool,可是表现的有点冗余。我已经用下面一种error机制作为替代。我觉得我的更好

var (
x, y, z T
err      error 

x, err = foo()

if err == nil {
y, err = bar(x)
}

if err == nil {
z, err = baz(y)
}
 
if err == nil { 
// do something w/ z
}

return err 

 
//出于好奇。请问有人用过我这样的风格然后有发现过缺点吗?或者这样的风格并不好?尽管我觉得非常好

Just curious, has anyone else used this sort of thing and found a pitfall? Or perhaps has an opinion as to why it isn't actually nice?

I think it's nice =].

 

看了上面两种错误处理风格。大家应该已经看出了部分端倪:第一种是比較传统的error处理方式,另外一种是作者觉得比較创新的error处理方式。

先不说第一种的优缺点,

另外一种首先在开头设置了全部接收error的变量。然后后面的error处理方式是环环相扣,冗余度很之高。且直到最后才return,也就是说假设代码够长。那你得看完中间全部的处理过程。在这里你仅仅有读完了整段代码才知道foo()产生的错误究竟是怎么处理的。

 

然后一个评论中提出了一种个人认为不错的风格:

  value,err :=  bar()

  if err != nil {

        goto handleError

  }

.

.

.

.

  handleError:

        return err

 

在这样的风格中不须要去知道goto和label中间的代码。能够直接进行错误处理并返回,因此代码简洁、可读性强、性能高且冗余度低。

另一个评论提出了一种非常特别的风格:

if x, err := foo(); err != nil {
   return err
} else if y, err := bar(x); err != nil {
   return err
} else if z, err := baz(y); err != nil {
   return err
} else {
   // do something w/ x,y,z

   return nil
}

这样的写法的代码比較简洁,return的地方一眼便可得知。

 

以下这样的风格能够节省大量的if语句

func checkErr( err error) {

     if  err != nil {

                    //deal error here

     }

}

func main() {

     ting,err := whatever()

     checkErr(err)

}

以下再说说我个人对提问中第二段代码的看法,主要有3点:

     1.在第二段代码中,全部的有意义的代码都是环环相扣,每个if和return都要记在脑袋里,详细能够看下这篇文章:代码的嵌套——各种状态的组合。在第一段代码中全部的错误处理都是在产生错误代码的以下,非常easy发现什么代码导致了某个错误。并且在那些if代码块之后。你不须要操心之前的x,y,z。由于它们都是合法的。可是在第二段代码中,永远不能知道x,y,z是否合法,每次都得继续验证前面的值。

     2.由于第二段代码的错误处理和返回方式(环环相扣),我们就无法得知error的详细位置,唯一能做的就是彻底放弃然后无奈的说一句“代码有BUG了”,仅此而已。

     3.每次你往第二段代码的函数添加新的代码的时候,都要放在一个if代码快中。相反在第一段代码中,就不须要,由于仅仅有错误处理在if中。其它的都在外部处理

 

这里仅仅是一个简单的抛砖引玉。希望大家能发表下寻常项目中使用的错误处理机制,一起讨论。






本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5152862.html,如需转载请自行联系原作者