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 相关文章推荐
Go Gin实现文件上传下载的示例代码
Apr 02 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
Golang 使用Map实现去重与set的功能操作
Apr 29 Golang
golang DNS服务器的简单实现操作
Apr 30 Golang
golang日志包logger的用法详解
May 05 Golang
Golang: 内建容器的用法
May 05 Golang
golang gopm get -g -v 无法获取第三方库的解决方案
May 05 Golang
手把手教你导入Go语言第三方库
Aug 04 Golang
浅谈GO中的Channel以及死锁的造成
Mar 18 Golang
victoriaMetrics库布隆过滤器初始化及使用详解
Apr 05 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 Golang
在ubuntu下安装go开发环境的全过程
Aug 05 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实现查询百度google收录情况(示例代码)
2013/08/02 PHP
PHP的password_hash()使用实例
2014/03/17 PHP
PHP动态生成指定大小随机图片的方法
2016/03/25 PHP
php+js实现百度地图多点标注的方法
2016/11/30 PHP
自写的利用PDO对mysql数据库增删改查操作类
2018/02/19 PHP
PHP PDOStatement::setFetchMode讲解
2019/02/03 PHP
jquery nth-child()选择器的简单应用
2010/07/10 Javascript
jQuery对象[0]是什么含义?
2010/07/31 Javascript
ASP.NET中基于JQUERY的高性能的TreeView补充
2011/02/23 Javascript
一个简单的动态加载js和css的jquery代码
2014/09/01 Javascript
Node.js 的异步 IO 性能探讨
2014/10/08 Javascript
jquery实现可自动收缩的TAB网页选项卡代码
2015/09/06 Javascript
javascript使用闭包模拟对象的私有属性和方法
2016/10/05 Javascript
微信小程序 PHP后端form表单提交实例详解
2017/01/12 Javascript
JavaScript实现form表单的多文件上传
2020/03/27 Javascript
详解如何为你的angular app构建一个第三方库
2018/12/07 Javascript
微信小程序当前时间时段选择器插件使用方法详解
2018/12/28 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
2019/03/07 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
npm的lock机制解析
2019/06/20 Javascript
Layer+Echarts构建弹出层折线图的方法
2019/09/25 Javascript
详解Vue 数据更新了但页面没有更新的 7 种情况汇总及延伸总结
2020/05/28 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
React中使用Vditor自定义图片详解
2020/12/25 Javascript
[01:07:41]IG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
[35:55]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第一场 12.11
2020/12/13 DOTA
Python中使用hashlib模块处理算法的教程
2015/04/28 Python
Flask Web开发入门之文件上传(八)
2018/08/17 Python
ActiveMQ:使用Python访问ActiveMQ的方法
2019/01/30 Python
python函数的万能参数传参详解
2019/07/26 Python
python设置代理和添加镜像源的方法
2020/02/14 Python
个性化皮包、小袋、生活配件:Mon Purse
2019/03/26 全球购物
四年的大学生生活自我评价
2013/12/09 职场文书
云南省召开党的群众路线教育实践活动总结会议新闻稿
2014/10/21 职场文书
思想政治表现评语
2015/01/04 职场文书
元旦联欢晚会主持词
2015/07/01 职场文书