思考
我们可以通过 无buffer 的 channel来进行通知,那有没有更简便的方法?
WaitGroup
WaitGroup是什么?
WaitGroup
等待一组Goroutine的完成,main goroutine 调用 Add 来设置要等待的 goroutine 的数量。然后每个 goroutine 运行并在完成时调用 Done。同时,Wait 可以用来阻塞,直到所有的 goroutine 都完成
1 | go复制代码type WaitGroup struct { |
示例
1 | go复制代码func main() { |
问题
- 并发的时候
url
的值可能会发生混淆,因为在循环的时候使用的是相同的实例url,当执行downloadFile(url)
的时候,url的值可能已经被更改
如何检测这种情况呢?
go vet
如何解决?
* 启动的时候将当前值绑定给闭包
* 创建一个新的变量
- 如何知道启动的goroutine组里边他们的运行情况?是否发生错误了?如何返回错误?假如某一个goroutine发生错误了,如何取消其他goroutine,避免资源的浪费
- 如何控制超时或者取消
errgroup
errgroup是什么?
提供同步,错误传播,一组gorouines的context的取消,致力于解决通用任务的子任务们
函数签名
1 | go复制代码// A Group is a collection of goroutines working on subtasks that are part of |
func WithContext
1 | go复制代码func WithContext(ctx context.Context ) (*Group , context.Context ) |
WithContext 返回一个新的 Group 和一个从 ctx 派生的关联上下文。会创建一个带取消的Group
派生的 Context 在第一次传递给 Go 的函数返回非 nil 错误时或第一次 Wait 返回时被取消,以先发生者为准。
func (*Group) Go
1 | go复制代码func (g * Group ) Go(f func() error) |
Go 在一个新的 goroutine 中调用输入的函数。
第一次调用返回非nil 错误并且会执行取消逻辑;它的错误将由 Wait 返回。
func (*Group) Wait
1 | go复制代码func (g * Group ) Wait() error |
Wait 阻塞,直到所有来自 Go 方法的函数调用都返回,然后从它们返回第一个非 nil 错误(如果有)。
示例
传播错误
1 | go复制代码func main() { |
取消其他子任务
1 | go复制代码func main() { |
总结
- 如果多个
Goroutine
出现错误,只会获取到第一个出错的Goroutine
的错误信息,其他出错的Goroutine
的错误信息将不会被感知到。 errgroup.Group
在出现错误或者等待结束后都会调用Context
对象 的cancel
方法同步取消信号
参考链接
本文转载自: 掘金