Go 服务开发高手课
徐逸
头部大厂资深 Go 技术专家、前腾讯资深工程师
771 人已学习
新⼈⾸单¥59
Go 服务开发高手课
15
15
1.0x
00:00/00:00
登录|注册

06|并发等待:如何降低实时系统的响应延时?

你好,我是徐逸。
在上节课中,我们学习了如何借助资源复用来降低 Golang 运行时的资源损耗,从而提升单机吞吐。在资源复用的技巧里,我们重点强调了协程池这一关键技巧。
有了协程并发的运用,自然少不了并发相关的技术。所以在今天的课程里,我们就来聊一聊协程并发等待技术——WaitGroup 类型和 errgroup 包。只有熟练地掌握这些并发技术,我们才能够在面对各种并发场景时,更快、更好地解决各种并发问题。
首先,我们来想一个问题:倘若我们需要向多个下游发起并发请求,并且必须得等待所有请求返回时,你会用 Golang 的哪个并发类型来实现呢?
图1 并发调用

WaitGroup 类型

当面对这种场景时,常规解决方法是用 Golang 的基础并发类型 WaitGroup。WaitGroup 的作用是阻塞等待多个并发任务执行完成。WaitGroup 类型主要包含下面几个方法。
func (wg *WaitGroup) Add(delta int)
func (wg *WaitGroup) Done()
func (wg *WaitGroup) Wait()
第一个是 Add 方法,在任务运行之前,需要调用 Add 方法,用于设置需要等待完成的任务数,Add 方法传进去的数值之和,需要和任务数相等。
第二个是 Done 方法,每个任务完成时,需要调用 Done 方法,用于告知 WaitGroup 对象已经有一个任务运行完成。
第三个是 Wait 方法,当需要等待所有并发任务完成时,调用 Wait 方法,用于阻塞主协程。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
  • 解释
  • 总结

1. WaitGroup类型是Golang的基础并发类型,用于阻塞等待多个并发任务执行完成,包含Add、Done和Wait方法。 2. errgroup包是Golang提供的并发扩展库,对WaitGroup进行了封装,在并发等待的基础功能上提供了错误处理和任务取消功能。 3. Group类型的Go方法用于传入具有错误返回值的函数类型,Wait方法会阻塞等待所有传入Go方法的函数全部运行完毕,并且在任务完成后能够对错误进行处理。 4. 任务取消功能通过WithContext函数创建Group对象,传入Go方法的函数需要实现select-done模式,利用context来停止所有相关任务。 5. errgroup包还可以限制同时并发运行的最大协程数,通过SetLimit方法设置可同时运行的最大协程数,达到最大协程数时会阻塞创建新协程运行任务。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 服务开发高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(2)

  • 最新
  • 精选
  • func TestCancel(t *testing.T) { results := make([]string, len(urls)) // 用WithContext函数创建Group对象 eg, ctx := errgroup.WithContext(context.Background()) for index, url := range urls { url := url index := index // 调用Go方法 eg.Go(func() error { select { case <-ctx.Done(): // select-done模式取消运行 return errors.New("task is cancelled") default: // Fetch the URL. resp, err := http.Get(url) if err != nil { return err // 返回错误 } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return err // 返回错误 } results[index] = string(body) return nil } }) } // Wait for all HTTP fetches to complete. // 等待所有任务执行完成,并对错误进行处理 if err := eg.Wait(); err != nil { fmt.Println("Failured fetched all URLs.") } } 这个方法感觉直接用可以cancle的context会不会比较好,如果检测到错误直接cancel掉。现在感觉这个例子虽然支持cancel,虽然在讲cancel,但是例子没有支持cancel,看起来怪怪的。
    2024-12-20归属地:北京
  • lJ
    可以基于 WaitGroup 和一个错误通道(error channel,容量不小于控制的协程并发数,避免阻塞)来收集并发协程中的错误信息,任务协程发生的错误写入err channel中,开启一个协程读取err channel。也可以初始化一个全局的错误切片errs,在协程出错时将err赋值给errs。 开源实现有 1、github.com/facebookgo/errgroup,扩展了标准库的sync.WaitGroup,errors收集协程执行时发生的错误 type Group struct { wg sync.WaitGroup mu sync.Mutex errors MultiError } 2、github.com/vardius/gollback,gollback.All方法返回所有的错误 本质上都是通过err切片保存任务协程中的错误信息
    2024-12-20归属地:江苏
收起评论
显示
设置
留言
2
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部