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 原生http web 服务跨域restful api的写法介绍
Apr 27 Golang
golang 生成对应的数据表struct定义操作
Apr 28 Golang
完美解决golang go get私有仓库的问题
May 05 Golang
浅谈Golang 切片(slice)扩容机制的原理
Jun 09 Golang
Golang表示枚举类型的详细讲解
Sep 04 Golang
golang实现一个简单的websocket聊天室功能
Oct 05 Golang
Golang中channel的原理解读(推荐)
Oct 16 Golang
深入理解go缓存库freecache的使用
Feb 15 Golang
如何利用golang运用mysql数据库
Mar 13 Golang
简单聊聊Golang中defer预计算参数
Mar 25 Golang
Go语言安装并操作redis的go-redis库
Apr 14 Golang
GO语言异常处理分析 err接口及defer延迟
Apr 14 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支持页面回退的两种方法
2008/01/10 PHP
jqPlot 图表中文API使用文档及源码和在线示例
2012/02/07 Javascript
javascript实现信息的显示和隐藏如注册页面
2013/12/03 Javascript
JS数组(Array)处理函数整理
2014/12/07 Javascript
js图片跟随鼠标移动代码
2015/11/26 Javascript
原生js实现返回顶部缓冲效果
2017/01/18 Javascript
浅谈Vue.js 组件中的v-on绑定自定义事件理解
2017/11/17 Javascript
在Vue中使用highCharts绘制3d饼图的方法
2018/02/08 Javascript
JS插件clipboard.js实现一键复制粘贴功能
2020/12/04 Javascript
深入理解JavaScript 箭头函数
2019/05/30 Javascript
Vue中全局变量的定义和使用
2019/06/05 Javascript
使用layui的router来进行传参的实现方法
2019/09/06 Javascript
微信小程序监听用户登录事件的实现方法
2019/11/11 Javascript
微信小程序拖拽排序列表的示例代码
2020/07/08 Javascript
[52:29]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#3Secret VS OG第三局
2016/03/03 DOTA
[00:23]魔方之谜解锁款式
2018/12/20 DOTA
Linux下Python获取IP地址的代码
2014/11/30 Python
在Python中使用base64模块处理字符编码的教程
2015/04/28 Python
深入探究Python中变量的拷贝和作用域问题
2015/05/05 Python
SQLite3中文编码 Python的实现
2017/01/11 Python
Python利用Beautiful Soup模块搜索内容详解
2017/03/29 Python
python3.6.3+opencv3.3.0实现动态人脸捕获
2018/05/25 Python
Python依赖包整体迁移方法详解
2019/08/15 Python
Python collections模块使用方法详解
2019/08/28 Python
python 实现dict转json并保存文件
2019/12/05 Python
Python多线程threading创建及使用方法解析
2020/06/17 Python
关于python中导入文件到list的问题
2020/10/31 Python
解释一下ruby中的特殊方法与特殊类
2013/02/26 面试题
社团活动总结怎么写
2014/06/30 职场文书
2014年团支部工作总结
2014/11/17 职场文书
2014年计生工作总结
2014/11/21 职场文书
新郎婚礼答谢词
2015/01/04 职场文书
golang elasticsearch Client的使用详解
2021/05/05 Golang
Pytorch中Softmax和LogSoftmax的使用详解
2021/06/05 Python
MySQL 亿级数据导入导出及迁移笔记
2021/06/18 MySQL
Python中tqdm的使用和例子
2022/09/23 Python