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

前端之家收集整理的这篇文章主要介绍了Go语言 关于go error处理风格的一些讨论和个人观点(上)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

原创文章,转载请注明出处:服务器非业余研究-sunface

最近看谷歌go group里面有很多讨论go error处理风格的问题,颇有启发,现在跟大家分享一下,首先请看一个提问:

@H_403_9@Hi folks,


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

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

@H_403_9@
y,err := bar(x)
z,err := baz(y)
if err != nil {
return err
}

@H_403_9@
// do something w/ z
return nil

@H_403_9@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:
@H_403_9@//上段代码很cool,但是表现的有点冗余,我已经用以下一种error机制作为替代,我认为我的更好

@H_403_9@
var (
err error
)
if err == nil {
if err == nil {
}
if err == nil {
// do something w/ z
}
return err


//出于好奇,请问有人用过我这种风格然后有发现过缺点吗?或者这种风格并不好?虽然我认为很好

@H_403_9@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,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都要记在脑袋里,具体可以看下这篇文章代码的嵌套——各种状态的组合。在第一段代码中所有的错误处理都是在产生错误代码的下面,很容易发现什么代码导致了某个错误,而且在那些if代码块之后,你不需要担心之前的x,z,因为它们都是合法的。但是在第二段代码中,永远不能知道x,z是否合法,每次都得继续验证前面的值。

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

3.每次你往第二段代码函数增加新的代码的时候,都要放在一个if代码快中。相反在第一段代码中,就不需要,因为只有错误处理在if中,其他的都在外部处理

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

猜你在找的Go相关文章