干货大放送~golang错误处理之error

Posted ITPUB技术小栈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货大放送~golang错误处理之error相关的知识,希望对你有一定的参考价值。

golang中没有try/catch这样的异常处理机制,只能依靠返回值来做状态是否出错判断(当然它有个panic/recover机制,但一般只处理意想不到的错误)。

对于函数的返回值,惯例是最后一个参数返回error对象,来表示函数运行的状态。
如:

  1. n, err := func()

  2. if err != nil {

  3.    ...//process error

  4. }

或者写在一起

  1. if n, err := func(); err != nil {

  2.    ...//process error

  3. }

error对象可以由errors.New()或fmt.Errorf()构造。
如:

  1. var dividedErr = errors.New("Cant divided by 0")

  1. err := fmt.Errorf("%d cant divided by 0", arg

我们先来看看error到底是什么类型。
error在标准库中被定义为一个接口类型,该接口只有一个Error()方法:

  1. type error interface {

  2.   Error() string

  3. }

也就是说,自定义的结构只需要拥有Error()方法,就相当于实现了error接口。

我们可以创建一个结构体,并实现Error()方法,就能根据自己的意愿构造error对象了。
如:

  1. type division struct {

  2.    arg int

  3.    str string

  4. }


  5. func (e *division) Error() string {

  6.    return fmt.Sprintf("%d %s", e.arg, e.str)

  7. }


  8. func divideCheck(arg1, arg2 int) (error) {

  9.    if arg2 == 0 {

  10.      return &division{arg1, "can't divided by 0"}

  11.    }

  12.    return nil

  13. }

再来看一个例子,检查一组数据中是否有不能除(即除数为0)的情况,如果有则返回出错。

代码如下:

  1. package main


  2. import "fmt"


  3. func divideCheck(arg1, arg2 int) (error) {

  4.    if arg2 == 0 {

  5.      return fmt.Errorf("%d can't divided by 0", arg1)

  6.    }

  7.    return nil

  8. }


  9. func main() {

  10.    var err error


  11.    err = divideCheck(4, 2)

  12.    if err != nil {

  13.      fmt.Println(err)

  14.      return

  15.   }


  16.    err = divideCheck(8, 0)

  17.    if err != nil {

  18.      fmt.Println(err)

  19.      return

  20.    }

  21. }

我们实现了这个功能,但是这样的代码非常不优雅,每执行一次函数调用都至少要用3行来做错误处理。

下面来优化一下。我们需要实现的功能是,只要有一个数不能除,就返回出错。那么只需要把每次检查后的状态存储到内部状态变量里,在全部处理完成后再检查这个变量就行了。
代码如下:

  1. package main


  2. import "fmt"


  3. type division struct {

  4.   err error

  5. }


  6. func (this *division)DivideCheck(arg1, arg2 int) {

  7.   if this.err != nil {

  8.     return

  9.   }

  10.   if arg2 == 0 {

  11.     this.err = fmt.Errorf("%d can't divided by 0", arg1)

  12.     return

  13.   }

  14. }


  15. func (this *division)Err() error {

  16.    return this.err

  17. }


  18. func main() {

  19.    d := new(division)

  20.    d.DivideCheck(4, 2)

  21.    d.DivideCheck(8, 0)

  22.    if d.Err() != nil {

  23.      fmt.Println(d.Err())

  24.    }

  25. }

这么做代码就优雅多了,并且在每次检查前都判断内部状态是否已经出错,出错就马上返回,几乎没有性能损失。

golang的错误处理是经常被诟病的地方,但如果懂得以go的方式编程,还是可以做的挺优雅的~



终极折扣进行时!盛宴,不容错过!
.


作为国内数据库与大数据领域最大规模的技术盛宴,2016第七届中国数据库技术大会(DTCC)将于2016年5月12日-14日召开。

大会云集了国内外顶尖专家,共同探讨mysql、智能数据平台、数据治理、大数据创业、大数据深度学习等领域的前瞻性热点话题与技术,为数据库人群、大数据从业人员、广大互联网人士及行业相关人士提供最具价值的交流平台。

最后折扣期!4月20日前,订购DTCC大会门票可享8.8折优惠! 团购更有折上折!
报名参会可直接点击阅读原文。

更多详情可访问DTCC 2016官网:
http://dtcc.it168.com/


以上是关于干货大放送~golang错误处理之error的主要内容,如果未能解决你的问题,请参考以下文章

干货收藏!50+ 最棒的 DevOps 开源工具大放送

WOT干货大放送:大数据架构发展趋势及探索实践分享

Golang:error包错误处理

golang 错误处理channel+error真的香

golang 错误处理channel+error真的香

golang 错误处理channel+error真的香