Go语言扩展原语之ErrGroup的用法详解

 更新时间:2023年07月18日 11:49:11   作者:码一行  
除标准库中提供的同步原语外,Go语言还在子仓库sync中提供了4种扩展原语,本文主要为大家介绍的是其中的golang/sync/errgroup.Group,感兴趣的小伙伴可以了解一下

概述

除标准库中提供的同步原语外,Go语言还在子仓库sync中提供了4种扩展原语:

  • golang/sync/errgroup.Group
  • golang/sync/semaphore.Weighted
  • golang/sync/singleflight.Group
  • golang/sync/syncmap.Map

其中 golang/sync/syncmap.MapGo1.9 中移植到了标准库中。

接下来介绍Go语言在扩展包中提供的3种同步原语 —— golang/sync/errgroup.Group

ErrGroup

golang/sync/errgroup.Group 为我们在一组 Goroutine 中提供了同步、错误传播以及上下文取消功能,我们可以使用这种方式并行获取网页数据:

var g errgroup.Group
var urls = []string{
    "http://www.golang.org",
    "http://www.google.com"
}
for i := range urls {
    url := urls[i]
    g.Go(func() error {
        resp, err := http.Get(url)
        if err == nil {
            resp.Body.Close()
        }
        return err
    })
}
if err := g.Wait(); err == nil {
    fmt.Println("Successfully fetched all URLs.")
}

golang/sync/errgroup.Group.Go 方法能够创建一个 Goroutine 并在其中执行传入的函数,而 golang/sync/errgroup.Group.Wait 会等待所有 Goroutine 返回,该方法的不同返回结果有不同的含义:

  • 如果返回错误 —— 这一组 Goroutine 最少返回一个错误
  • 如果返回空值 —— 所有 Goroutine 都成功执行

结构体

golang/sync/errgroup.Group 结构体有 3 个比较重要的部分组成

  • cancel —— 创建 context.Context 时返回的取消函数,用于在多个 Goroutine 之间同步取消信号
  • wg —— 用于等待一组 Goroutine 完成子任务的同步原语
  • errOnce —— 用于保证只接收一个子任务返回的错误
type Group struct {
    cancel func()
    wg sync.WaitGroup
    errOnce sync.Once
    err     error
}

这些字段共同组成了 golang/sync/errgroup.Group 结构体并为我提供同步错误传播以及上下文取消等功能。

接口

我们能通过 golang/sync/errgroup.WithContext 构造器创新的 golang/sync/errgroup.Group 结构体:

func WithContext(ctx context.Context) (*Group, context.Context) {
    ctx, cancel := context.WithCancel(ctx)
    return &Group{cancel: cancel}, ctx
}

运行新的并行子任务需要使用 golang/sync/errgroup.Group.Go 方法,这个方法的执行过程如下:

  • 调用 sync.WaitGroup.Add 增加待处理的任务
  • 创建新的 Goroutine 并运行子任务
  • 返回错误时及时调用 cancel 并对 err 赋值,只有最早返回的错误才会被上游感知到,后续错误都会被舍弃。
func (g *Group) Go(){
    g.wg.Add(1)
    go func() {
        defer g.wg.Done()
        if err := f(); err := nil {
            g.errOnce.Do(func () {
                g.err = err
                if g.cancel != nil {
                    g.cancel()
                }
            })
        }
    }()
}
func (g *Group) Wait() error {
    g.wg.Wait()
    if g.cancel != nil {
        g.cancel()
    }
    return g.err
}

另一个用于等待的 golang/sync/errgroup.Group.Wait 方法只是调用了 sync.WaitGroup.Wait,在子任务全部完成时取消 context.Context 并返回可能出现的错误。

小结

golang/sync/errgroup.Group 的实现没有涉及底层和运行包中的API,它只是封装了基本同步语义以提供更加复杂的功能。我们在使用它时需要注意两个问题:

  • golang/sync/errgroup.Group 在出现错误或者等待结束后,会调用 context.Contextcancel 方法同步取消信号
  • 只有第一个出现的错误才会被返回,剩余错误会被直接丢弃

到此这篇关于Go语言扩展原语之ErrGroup的用法详解的文章就介绍到这了,更多相关Go ErrGroup内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang定时器的2种实现方法与区别

    Golang定时器的2种实现方法与区别

    这篇文章主要给大家介绍了关于Golang定时器的2种实现方法与区别的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Golang命令行进行debug调试操作

    Golang命令行进行debug调试操作

    今天小编就为大家分享一篇关于,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • Go语言基于HTTP的内存缓存服务的实现

    Go语言基于HTTP的内存缓存服务的实现

    这篇文章主要介绍了Go语言基于HTTP的内存缓存服务,本程序采用REST接口,支持设置(Set)、获取(Get)和删除(Del)这3个基本操作,同时还支持对缓存服务状态进行查询,需要的朋友可以参考下
    2022-08-08
  • golang字符串本质与原理详解

    golang字符串本质与原理详解

    这篇文章主要介绍了golang字符串本质与原理详解,golang中的字符串指的是所有8比特位字节字符串的集合,通常是UTF-8编码的文本,更多相关内容需要的小伙伴可以参考一下
    2022-06-06
  • LRU LFU TinyLFU缓存算法实例详解

    LRU LFU TinyLFU缓存算法实例详解

    这篇文章主要为大家介绍了LRU LFU TinyLFU缓存算法实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Golang Gin 中间件 Next()方法示例详解

    Golang Gin 中间件 Next()方法示例详解

    这篇文章主要介绍了Golang Gin 中间件 Next()方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • Golang 官方依赖注入工具wire示例详解

    Golang 官方依赖注入工具wire示例详解

    这篇文章主要为大家介绍了Golang 官方依赖注入工具wire示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • 解决goland 导入项目后import里的包报红问题

    解决goland 导入项目后import里的包报红问题

    这篇文章主要介绍了解决goland 导入项目后import里的包报红问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • go:gin输出日志文件方式

    go:gin输出日志文件方式

    这篇文章主要介绍了go:gin输出日志文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 超详细Go语言中JSON处理技巧分享

    超详细Go语言中JSON处理技巧分享

    这篇文章主要为大家总结了go语言中对JSON数据结构和结构体之间相互转换问题及解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-06-06

最新评论