go goroutine 怎样进行错误处理


Posted in Golang onJuly 16, 2021

前言

在 Go 语言程序开发中,goroutine 的使用是比较频繁的,因此在日常编码的时候 goroutine 里的错误处理,怎么做会比较好呢?

一般我们的业务代码如下:

func main() {
 var wg sync.WaitGroup
 wg.Add(2)
 go func() {
  //... 业务逻辑
  wg.Done()
 }()
 go func() {
  //... 业务逻辑
  wg.Done()
 }()
 wg.Wait()
}

在上面的代码中,我们运行了多个 goroutine,每个协程又是单独行动的,想要抛出 error 错误信息,也不怎么明智。

通过错误日志记录

常用的第一种方法:通过把错误记录写入到日志文件中,再结合相关的 logtail 进行采集和梳理。

但这又会引入新的问题,那就是调用错误日志的方法写的到处都是,代码结构也比较乱、不直观。

最重要的是无法针对 error 做特定的逻辑处理和流转。

利用 channel 传输

大家可能会想到 Go 的经典哲学:不要通过共享内存来通信,而是通过通信来实现内存共享(Do not communicate by sharing memory; instead, share memory by communicating)。

第二种方法:利用 channel 来传输多个 goroutine 中的 errors:

func main() {
 cherrors := make(chan error)
 wgDone := make(chan bool)

 var wg sync.WaitGroup
 wg.Add(2)
 go func() {
  //... 业务逻辑
  wg.Done()
 }()
 go func() {
  //... 业务逻辑
  err := returnErr()
  if err != nil {
   cherrors <- err
  }
  wg.Done()
 }()
 go func() {
  wg.Wait()
  close(wgDone)
 }()

 select {
 case <-wgDone:
  break
 case err := <-cherrors:
  close(cherrors)
  fmt.Println(err)
 }

 time.Sleep(time.Second)
}

func returnErr() error {
 return errors.New("出错啦。。我是错误信息")
}

虽然使用 channel 后已经方便了不少,但编写 channel 还要关心一些非业务向的逻辑。

使用 sync/errgroup

第三种方法,就是使用官方提供的 golang.org/x/sync/errgroup 标准库:

type Group
    func WithContext(ctx context.Context) (*Group, context.Context)
    func (g *Group) Go(f func() error)
    func (g *Group) Wait() error
  • Go:启动一个协程,在新的 goroutine 中调用给定的函数。
  • Wait:等待协程结束,直到 Go 方法中的所有函数调用都返回,然后返回其中第一个非零错误(如果有错误的话)。

结合其特性能够非常便捷的针对多 goroutine 进行错误处理:

func main() {
 group := new(errgroup.Group)

 nums := []int{-1, 0, 1}
 for _, num := range nums {
  num := num
  group.Go(func() error {
   res, err := output(num)
   fmt.Println(res)
   return err
  })
 }

 if err := group.Wait(); err != nil {
  fmt.Println("Get errors: ", err)
 } else {
  fmt.Println("Get all num successfully!")
 }
}

func output(num int) (int, error) {
 if num < 0 {
  return 0, errors.New("math: square root error!")
 }
 return num, nil
}

每启动一个新的 goroutine 都直接使用 Group.Go 方法,在等待和错误处理上使用 Group.Wait 方法。

这种方法进行错误处理的好处是不需要关注非业务逻辑的控制代码,比较简洁明了。

总结

在 Go 语言中,goroutine 是一种常用的方法,为此我们需要更了解 goroutine 的一系列相关知识,像是 context、error处理等

在团队开发中,统一一定的规范,这样的代码阅读起来就会比较明朗,一些隐藏很深的 Bug 也会减少很多。

到此这篇关于go goroutine 怎样进行错误处理的文章就介绍到这了,更多相关go goroutine 错误处理内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Golang 相关文章推荐
golang判断key是否在map中的代码
Apr 24 Golang
使用Golang的channel交叉打印两个数组的操作
Apr 29 Golang
Go语言 go程释放操作(退出/销毁)
Apr 30 Golang
Go标准容器之Ring的使用说明
May 05 Golang
Go timer如何调度
Jun 09 Golang
golang 语言中错误处理机制
Aug 30 Golang
Golang表示枚举类型的详细讲解
Sep 04 Golang
一文搞懂Golang 时间和日期相关函数
Dec 06 Golang
Golang日志包的使用
Apr 20 Golang
GoFrame基于性能测试得知grpool使用场景
Jun 21 Golang
go开发alertmanger实现钉钉报警
Jul 16 #Golang
K8s部署发布Golang应用程序的实现方法
Jul 16 #Golang
入门学习Go的基本语法
Jul 07 #Golang
golang中字符串MD5生成方式总结
Jul 04 #Golang
golang fmt格式“占位符”的实例用法详解
Jul 04 #Golang
Go语言空白表示符_的实例用法
Jul 04 #Golang
Go 语言结构实例分析
Jul 04 #Golang
You might like
php自动加载机制的深入分析
2013/06/08 PHP
关于图片验证码设计的思考
2007/01/29 Javascript
控制页面按钮在后台执行期间不重复提交的JS方法
2013/06/24 Javascript
Jquery右下角抖动、浮动 实例代码(兼容ie6、FF)
2013/08/15 Javascript
通过pjax实现无刷新翻页(兼容新版jquery)
2014/01/31 Javascript
使用jquery.upload.js实现异步上传示例代码
2014/07/29 Javascript
JS文字球状放大效果代码分享
2015/08/19 Javascript
IE7浏览器窗口大小改变事件执行多次bug及IE6/IE7/IE8下resize问题
2015/08/21 Javascript
JS 终止执行的实现方法
2016/11/24 Javascript
jQuery中Chosen三级联动功能实例代码
2017/03/07 Javascript
jQuery中animate()的使用方法及解决$(”body“).animate({“scrollTop”:top})不被Firefox支持的问题
2017/04/04 jQuery
node.js中EJS 模板快速入门教程
2017/05/08 Javascript
微信小程序progress组件使用详解
2018/01/31 Javascript
使用javascript函数编写简单银行取钱存钱流程
2018/05/26 Javascript
基于layui框架响应式布局的一些使用详解
2019/09/16 Javascript
详解Vue的watch中的immediate与watch是什么意思
2019/12/30 Javascript
vue从零实现一个消息通知组件的方法详解
2020/03/16 Javascript
element中el-container容器与div布局区分详解
2020/05/13 Javascript
django简单的前后端分离的数据传输实例 axios
2020/05/18 Javascript
在vue中嵌入外部网站的实现
2020/11/13 Javascript
基于h5py的使用及数据封装代码
2019/12/26 Python
Python对Tornado请求与响应的数据处理
2020/02/12 Python
500行python代码实现飞机大战
2020/04/24 Python
详解tensorflow2.x版本无法调用gpu的一种解决方法
2020/05/25 Python
Python中random模块常用方法的使用教程
2020/10/04 Python
利用pipenv和pyenv管理多个相互独立的Python虚拟开发环境
2020/11/01 Python
美国电视购物HSN官网:HSN
2016/09/07 全球购物
Geekbuying波兰:购买中国电子产品
2019/10/20 全球购物
高中数学教师求职信
2013/10/30 职场文书
完美主义个人的自我评价
2014/02/17 职场文书
小学教师评语大全
2014/04/23 职场文书
项目经理岗位职责
2015/01/31 职场文书
三十年同学聚会致辞
2015/07/28 职场文书
关于感恩的素材句子(38句)
2019/11/11 职场文书
MySQL 数据库 增删查改、克隆、外键 等操作
2022/05/11 MySQL
css让页脚保持在底部位置的四种方案
2022/07/23 HTML / CSS