errgroup.go (1615B)
1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package errgroup provides synchronization, error propagation, and Context 6 // cancelation for groups of goroutines working on subtasks of a common task. 7 package errgroup 8 9 import ( 10 "context" 11 "sync" 12 ) 13 14 // A Group is a collection of goroutines working on subtasks that are part of 15 // the same overall task. 16 // 17 // A zero Group is valid and does not cancel on error. 18 type Group struct { 19 cancel func() 20 21 wg sync.WaitGroup 22 23 errOnce sync.Once 24 err error 25 } 26 27 // WithContext returns a new Group and an associated Context derived from ctx. 28 // 29 // The derived Context is canceled the first time a function passed to Go 30 // returns a non-nil error or the first time Wait returns, whichever occurs 31 // first. 32 func WithContext(ctx context.Context) (*Group, context.Context) { 33 ctx, cancel := context.WithCancel(ctx) 34 return &Group{cancel: cancel}, ctx 35 } 36 37 // Wait blocks until all function calls from the Go method have returned, then 38 // returns the first non-nil error (if any) from them. 39 func (g *Group) Wait() error { 40 g.wg.Wait() 41 if g.cancel != nil { 42 g.cancel() 43 } 44 return g.err 45 } 46 47 // Go calls the given function in a new goroutine. 48 // 49 // The first call to return a non-nil error cancels the group; its error will be 50 // returned by Wait. 51 func (g *Group) Go(f func() error) { 52 g.wg.Add(1) 53 54 go func() { 55 defer g.wg.Done() 56 57 if err := f(); err != nil { 58 g.errOnce.Do(func() { 59 g.err = err 60 if g.cancel != nil { 61 g.cancel() 62 } 63 }) 64 } 65 }() 66 }