go goroutine 怎样进行错误处理

作者:mb60e703e6a8897 时间:2024-05-22 10:14:39 

目录
  • 前言

  • 通过错误日志记录

  • 利用 channel 传输

  • 使用 sync/errgroup

  • 总结

前言

在 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 也会减少很多。

来源:https://blog.51cto.com/niuben/3034753

标签:go,goroutine,错误处理
0
投稿

猜你喜欢

  • 如何设置mysql允许外部连接访问

    2024-01-15 05:22:14
  • Python实现淘宝秒杀功能的示例代码

    2021-05-26 09:41:49
  • 浅谈SQL Server中统计对于查询的影响分析

    2012-06-06 20:08:23
  • 关于vue中根据用户权限动态添加路由的问题

    2024-05-05 09:25:11
  • Python中JsonPath提取器和正则提取器

    2022-08-27 14:12:20
  • django admin组件使用方法详解

    2021-05-28 19:59:53
  • css样式命名规则

    2008-04-30 12:31:00
  • Python实现多进程的四种方式

    2022-03-14 10:48:46
  • 详解MySQL数据类型之数字类型正确使用

    2010-06-20 15:02:00
  • Python+django实现文件上传

    2022-08-31 20:52:22
  • 最新MySql8.27主从复制及SpringBoot项目中的读写分离实战教程

    2024-01-19 15:40:27
  • Python操作列表的常用方法分享

    2021-06-02 12:41:29
  • Python网页正文转换语音文件的操作方法

    2021-03-26 04:27:30
  • 让IE8支持eWebEditor在线编辑器

    2010-02-28 10:36:00
  • python PaddleSpeech实现婴儿啼哭识别

    2023-08-22 22:25:31
  • 运筹学-Python实现图论与最短距离

    2022-10-24 05:58:59
  • python解决12306登录验证码的实现

    2023-05-29 10:28:35
  • Git撤销已经推送(push)至远端仓库的提交(commit)信息操作

    2022-05-31 04:33:28
  • MySQL由浅入深探究存储过程

    2024-01-14 09:43:04
  • Pytorch 实现变量类型转换

    2021-09-27 23:35:47
  • asp之家 网络编程 m.aspxhome.com