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中semaphore(信号量)源码
Apr 03 Golang
Go语言操作数据库及其常规操作的示例代码
Apr 21 Golang
Golang 空map和未初始化map的注意事项说明
Apr 29 Golang
完美解决golang go get私有仓库的问题
May 05 Golang
golang 实现时间戳和时间的转化
May 07 Golang
基于Go语言构建RESTful API服务
Jul 25 Golang
Go Plugins插件的实现方式
Aug 07 Golang
golang实现一个简单的websocket聊天室功能
Oct 05 Golang
Golang流模式之grpc的四种数据流
Apr 13 Golang
Golang map映射的用法
Apr 22 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 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
使用php4加速网络传输
2006/10/09 PHP
php记录代码执行时间(实现代码)
2013/07/05 PHP
php中url传递中文字符,特殊危险字符的解决方法
2013/08/17 PHP
php面向对象中static静态属性与方法的内存位置分析
2015/02/08 PHP
PHP+mysql+ajax轻量级聊天室实现方法详解
2016/10/17 PHP
php中输出json对象的值(实现方法)
2018/03/07 PHP
跨域表单提交状态的变相判断代码
2009/11/12 Javascript
基于Jquery的开发个代阴影的对话框效果代码
2011/07/28 Javascript
js获取网页高度(详细整理)
2012/12/28 Javascript
复制js对象方法(详解)
2013/07/08 Javascript
js调试系列 源码定位与调试[基础篇]
2014/06/18 Javascript
javascript中递归函数用法注意点
2015/07/30 Javascript
jQuery实现的文字hover颜色渐变效果实例
2016/02/20 Javascript
Bootstrap基本插件学习笔记之Tooltip提示工具(18)
2016/12/08 Javascript
使用原生js封装的ajax实例(兼容jsonp)
2017/10/12 Javascript
基于vue实现网站前台的权限管理(前后端分离实践)
2018/01/13 Javascript
js 实现复选框只能选择一项的示例代码
2018/01/23 Javascript
js数组去重的N种方法(小结)
2018/06/07 Javascript
小程序:授权、登录、session_key、unionId的详解
2019/05/15 Javascript
Vue函数式组件的应用实例详解
2019/08/30 Javascript
在Vue 中实现循环渲染多个相同echarts图表
2020/07/20 Javascript
[07:47]DOTA2国际邀请赛采访专栏:探访Valve总部
2013/08/08 DOTA
Python中datetime常用时间处理方法
2015/06/15 Python
Python实现的字典值比较功能示例
2018/01/08 Python
Python动刷新抢12306火车票的代码(附源码)
2018/01/24 Python
对python3新增的byte类型详解
2018/12/04 Python
django使用haystack调用Elasticsearch实现索引搜索
2019/07/24 Python
PyTorch 随机数生成占用 CPU 过高的解决方法
2020/01/13 Python
PyCharm GUI界面开发和exe文件生成的实现
2020/03/04 Python
Python+appium框架原生代码实现App自动化测试详解
2020/03/06 Python
八月迷情观后感
2015/06/11 职场文书
员工担保书范本
2015/09/22 职场文书
2016年习总书记讲话学习心得体会
2016/01/20 职场文书
导游词之南昌滕王阁
2019/11/29 职场文书
vue实现锚点定位功能
2021/06/29 Vue.js
JavaScript架构localStorage特殊场景下二次封装操作
2022/06/21 Javascript