原创文章。转载请注明出处: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中。其它的都在外部处理

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

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

  1. [转载]VS2012编译C语言scanf函数error的解决方法

    在VS 2012 中编译 C 语言项目,如果使用了 scanf 函数,编译时便会提示如下错误: error C4996: 'scanf': This function or variable may ...

  2. kotlin 语言入门指南(二)--代码风格

    语言风格 这里整理了 kotlin 惯用的代码风格,如果你有喜爱的代码风格,可以在 github 上给 kotlin 提 pull request . 创建DTOs(POJSs/POCOs) 文件: ...

  3. GO_10:GO语言基础之error

    Go错误处理 Go 语言通过内置的错误接口提供了非常简单的错误处理机制. error类型是一个接口类型,这是它的定义: type error interface { Error() string } ...

  4. GO语言基础之error

    Go错误处理 Go 语言通过内置的错误接口提供了非常简单的错误处理机制. error类型是一个接口类型,这是它的定义: type error interface { Error() string } ...

  5. R语言保存文件 Error in save error writing to connection

    Error in save(filtered, file = paste(sampleName, "filtered", sep = "_")) :   err ...

  6. C语言学习笔记--#error 、 #line 和 #pragma 的使用

    1. #error 的用法 (1)#error 是一种预编译器指示字,用于生成一个编译错误消息 (2)用法:#error message //注意:message 不需要用双引号包围 (3)#erro ...

  7. R语言学习笔记-Error in ts(x):对象不是矩阵问题解决

    1.问题 在对时间序列进行拟合操作时,发生:Error in ts(x):对象不是矩阵的错误,而直接在arima()函数中使用时没有问题的. > sample<-c2 > sampl ...

  8. Golang优秀开源项目汇总, 10大流行Go语言开源项目, golang 开源项目全集(golang/go/wiki/Projects), GitHub上优秀的Go开源项目

    Golang优秀开源项目汇总(持续更新...)我把这个汇总放在github上了, 后面更新也会在github上更新. https://github.com/hackstoic/golang-open- ...

  9. 对《神奇的C语言》文中例子 5 代码的分析讨论

    在春节前,我曾经参与在<神奇的C语言>一文中的例子(5)的讨论,但限于评论内容的有限,现在本文再次对这个问题单独讨论.(此问题原貌,详见<神奇的C语言>,这里我将原文中的代码稍 ...

随机推荐

  1. Android自动化测试基础知识——MONKEY测试工具(转的)

    本周开始启动手机输入法simeiji的自动化测试,同时开始接触手机浏览器自动化测试.接下来会对android自动化测试工具和方法做一个专题研究. 第一篇介绍monkey测试工具. 1 自动化测试背景 ...

  2. Android保存之SharedPreferences

    Android中一共有四种存储方式: SharedPreferences 为其中的一种,具体还是看代码: package com.wyl.preferencetest; import android. ...

  3. Redis 突然报错 NOAUTH Authentication required

    查找相关资料,说是添加了密码 只需要在redis的配置文件redis.conf中开启requirepass就可以了,比如我设置我的访问密码是mypassword requirepass mypassw ...

  4. Week8(10月31日):并发

    Part I:提问  =========================== 1. 更新关联.删除关联数据,需要注意哪些问题?以Instructor类为例说明. 2. 已知某请假系统,请实现以下界面的 ...

  5. hibernate主键自动生成

    Entity类中,主键尽量使用可以为null值的类型,比如Integer,Long,String等,不要用int,long等.因为如果主键为null,则表示该实体类还没有保存到数据库,是一个临时状态( ...

  6. Android 修改底部导航栏navigationbar的颜色

    Android 修改底部导航栏navigationbar的颜色 getWindow().setNavigationBarColor(Color.BLUE); //写法一 getWindow().set ...

  7. Genymotion Unable to create Virtual Device:Connection timeout

    1.进入C:\Users\[UserName]\AppData\Local\Genymobile,打开genymotion.log,找到最后几句话:     九月 2 14:29:45 [Genymo ...

  8. linux 学习:环境变量设置

    一.临时环境变量 临时环境变量,只对当前打开的shell生效,shell关闭后,环境变量失效. 设置方法一: 分两步 MYPARA=hello export MYPARA 设置方法二:一步完成 exp ...

  9. 单实例支撑每天上亿个请求的SSDB

    SSDB 是一个 C++ 开发的 NoSQL 存储服务器, 支持 zset, map 数据结构, 可替代 Redis, 特别适合存储集合数据. SSDB 被开发和开源出来后, 已经在生产环境经受了3个 ...

  10. 比较优势 - MBA智库百科

    比较优势 - MBA智库百科 比较优势 出自 MBA智库百科(http://wiki.mbalib.com/)   这是一个消除歧义页--使用相同或相近标题,而主题不同的条目列表.如果您是通过某个内部 ...