在看《Go入门指南》的一种用闭包处理错误的模式时,里面提到了一种错误的优雅处理方式,减少我们重复写if err:=f(); err != nil{}式的代码,感觉很心动,做了下测试,结论如下:

  1. 能减少if err式的代码,代码可以变清新整洁。
  2. 使用存在限制:只有当错误需要结束调用时才可以使用这种方法,如果被调用函数返回错误,但调用者函数需处理错误后,向下继续执行,则不能采用这种方法。

经常的写法

我们在设计函数时,错误处理要遵循以下2个规则:

  1. 被调用函数如果有错误,需要传递给调用者,一定要返回
  2. 调用者收到返回的错误,一定不可忽视,忽视就是埋bug。如果调用者不处理,被调函数就需要设计成无错误返回。

我们都有这种感受,一个函数需要调用许多函数,然后处理他们的错误,光if err就写了一堆,比如下面的test()函数。

package main
import ("errors""log"
)
func main() {test()
}
func test() {if err := a(); err != nil {log.Println(err)}if err := b(); err != nil {log.Println(err)}if _, err := c(1, 0); err != nil {log.Println(err)}if _, err := d(1, 0); err != nil {log.Println(err)}
}
func a() error {return errors.New("error in a")
}
func b() error {return errors.New("error in b")
}
func c(x, y int) (int, error) {return x + y, errors.New("error in c")
}
func d(x, y int) (int, error) {if y == 0 {return 0, errors.New("error in d, divided by 0")}return x / y, nil
}

测试输出:

2018/10/24 14:42:40 error in a
2018/10/24 14:42:40 error in b
2018/10/24 14:42:40 error in c
2018/10/24 14:42:40 error in d, divided by 0
  • 优雅的方式

    借用2个小工具:

    1. check函数,把错误转化为panic
    2. 函数在defer中增加错误处理,从panic中恢复错误,并打印

    我们对test()函数进行小小的改造。

    package main
    import ("errors""fmt"
    )
    func main() {test()
    }
    func test() {defer func() {if r := recover(); r != nil {log.Println("got error: ", r)}}()var err errorerr = a()check(err)err = b()check(err)_, err = c(1, 2)check(err)_, err = d(1, 0)check(err)
    }
    func check(err error) {if err != nil {panic(err)}
    }
    func a() error {return errors.New("error in a")
    }
    func b() error {return errors.New("error in b")
    }
    func c(x, y int) (int, error) {return x + y, errors.New("error in c")
    }
    func d(x, y int) (int, error) {if y == 0 {return 0, errors.New("error in d, divided by 0")}return x / y, nil
    }
    

输出结果:

2018/10/24 17:29:35 got error: error in a

  • test()函数是清爽了不少,也不用一直if然后处理err了,但是这种处理把错误转化为panic,导致test()后续的代码无法再继续执行,b(), c(), d()几个函数就没法执行了。

    所以如果test()函数,遇到错误后就返回,就很适合这种优雅的方式。

    还可以更优雅吗

    test()函数中的defer看着挺碍眼的,我们还能让test()更简洁点吗,代码再优雅点?

    采用文章中介绍的办法,增加errorHandler()函数,实现对被调用函数的封装,为它增加defer函数,恢复panic报的错误,看代码。

    package main
    import ("errors""log"
    )
    func main() {errorHandler(test)()
    }
    func test() {var err errorerr = a()check(err)err = b()check(err)_, err = c(1, 2)check(err)_, err = d(1, 0)check(err)
    }
    func check(err error) {if err != nil {panic(err)}
    }
    // 封装f:为传入的函数增加defer
    func errorHandler(f func()) func() {return func() {defer func() {if r := recover(); r != nil {log.Println("got error: ", r)}}()f()}
    }
    func a() error {return errors.New("error in a")
    }
    func b() error {return errors.New("error in b")
    }
    func c(x, y int) (int, error) {return x + y, errors.New("error in c")
    }
    func d(x, y int) (int, error) {if y == 0 {return 0, errors.New("error in d, divided by 0")}return x / y, nil
    }
    

结果:

2018/10/24 17:36:41 got error:  error in a

还能再一次优雅吗

errorHandler()函数不够通用,它只接受无入参,无返回的函数。

  1. 如果这篇文章对你有帮助,不妨关注下我的Github,有文章会收到通知。
  2. 原文作者:大彬
  3. 如果喜欢本文,随意转载,但请保留此原文链接:http://lessisbetter.site/2018/10/24/go-handle-error/

如何优化Golang中重复的错误处理相关推荐

  1. 如何在Golang中返回错误?

    In Golang, we return errors explicitly using the return statement. This contrasts with the exception ...

  2. Hibernate3中重复引用hbm文件错误信息记录

    Hibernate3中重复引用hbm文件错误信息记录. 2018 八月 12 11:17:09,778 ERROR - Context initialization failed org.spring ...

  3. Windows系统中LOL登陆错误出现的服务器未响应优化教程

    当你怀着闲情逸致的心情打开英雄联盟的时候,一条"登录服务器未响应,您可能遇到一个网络错误,请检查您的网络." 让你当场石化,还有比这更坑的事吗?切莫心急,请使用下方教程解决Win系 ...

  4. golang中的goto

    使用 goto 退出多层循环 下面这段代码在满足条件时,需要连续退出两层循环,使用传统的编码方式如下: package mainimport "fmt"func main() {v ...

  5. Golang中的自动伸缩和自防御设计

    Raygun服务由许多活动组件构成,每个组件用于特定的任务.其中一个模块是用Golang编写的,负责对iOS崩溃报告进行处理.简而言之,它接受本机iOS崩溃报告,查找相关的dSYM文件,并生成开发者可 ...

  6. 因为返回有true ajax提示进入错误,jquery ajax中error返回错误解决办法

    转自:https://www.jb51.net/article/72198.htm 进入百度搜索此问题,发现有人这么说了一句 Jquery中的Ajax的async默认是true(异步请求),如果想一个 ...

  7. c语言间接级别不同_一个超复杂的间接递归——C语言初学者代码中的常见错误与瑕疵(6)...

    问题: 在该文的最后,曾提到完成的代码还有进一步改进的余地.本文完成了这个改进.所以本文讨论的并不是初学者代码中的常见错误与瑕疵,而是对我自己代码的改进和优化.标题只是为了保持系列的连续性. 改进 程 ...

  8. oracle delete not in 优化,Oracle中的sql语句优化

    1.选择最有效率的表名顺序(只在基于规则的优化器中有效) ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表driving table)将被最先处理,在 ...

  9. goto在golang中的用法

    使用 goto 退出多层循环 下面这段代码在满足条件时,需要连续退出两层循环,使用传统的编码方式如下: package mainimport "fmt"func main() {v ...

最新文章

  1. vue代理配置(vue+django前后端分离项目)
  2. linux c:关联变量的双for循环
  3. python中操作数据库中游标的使用方法
  4. 使用JDBC获取Oracle连接时报错
  5. 【渝粤题库】陕西师范大学200781 数据库原理及应用 作业
  6. scikit-learn——快速入门 - daniel-D(转)
  7. odoo 的字段。orm对象
  8. Linux内核多线程(三)
  9. Unity Using Interception and Policy Injection
  10. 删除已配对的View Security Server、View Replica Server
  11. excel如何批量查询手机号归属地
  12. TCP BBR - 一键安装最新内核并开启 TCP BBR
  13. 什么是Power Apps?
  14. 有实用简单的PS小技巧吗?下面几个小技巧你知道几个呢?
  15. 哥德巴赫猜想C++实现
  16. python雨课堂答案_雨课堂和微助教的比较分析
  17. 30 行代码实现,支付宝蚂蚁森林自动收能量!
  18. QQ技术攻略-原来隐藏着这么多秘密
  19. 基于JAVASEOUL设计师品牌代购商城计算机毕业设计源码+系统+lw文档+部署
  20. 【机器学习】LifeLong Learning(终身学习)介绍

热门文章

  1. date oracle 表中_从 MySQL 迁移数据到 Oracle 中的全过程
  2. 关键帧动画html例子,Bounce.js 是一个漂亮的CSS3关键帧动画生成工具和类库_前端开发者...
  3. 451 Research发布《2019年数据中心服务和基础设施预测》
  4. python处理文本格式_python linecache 处理固定格式文本数据的方法
  5. 成功解决Eclipse窗口布局混乱或者Eclipse窗口布局出现单独独立小窗口的问题(图文教程)
  6. Interview:算法岗位面试—10.30上午上海某信息公司(偏图算法)技术面试之单链表反转、给定整型数组和目标值 二分法查找+下午上海某金融公司(AI岗位,上市)CTO和主管技术面试之Xcepti
  7. ML之回归预测:利用13种机器学习算法对Boston(波士顿房价)数据集【13+1,506】进行回归预测(房价预测)+预测新数据得分
  8. Linux+pycharm下 安装tensorflow时遇到的bug
  9. 前台Vue、后台Django、设置axios解决csrf_token问题
  10. leetcode347 - Top K Frequent Elements - medium