Skip to content

Instantly share code, notes, and snippets.

@aprice
Last active April 26, 2017 19:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aprice/8f0b7f82046a0ac10b3b77eb15b7bc0e to your computer and use it in GitHub Desktop.
Save aprice/8f0b7f82046a0ac10b3b77eb15b7bc0e to your computer and use it in GitHub Desktop.
Simple, un-typed fan-in/fan-out result collator. Easy to customize for type safety.
type Collator struct {
results chan interface{}
errors chan error
wg *sync.WaitGroup
}
func NewCollator() *Collator {
return &Collator{
results: make(chan interface{}),
errors: make(chan error),
wg: new(sync.WaitGroup),
}
}
// Start workers, THEN call Collate() to collect results and errors.
func (c *Collator) Collate() ([]interface{}, []error) {
wgc := make(chan struct{})
go func() {
c.wg.Wait()
wgc <- struct{}{}
}()
errs := make([]error, 0)
results := make([]interface{}, 0)
done := false
for !done {
select {
case err := <-c.errors:
errs = append(errs, err)
case result := <-c.results:
results = append(results, result)
case <-wgc:
done = true
}
}
return results, errs
}
// Call with result immediately before returning from goroutine.
func (c *Collator) Success(result interface{}) {
c.results <- result
c.wg.Done()
}
// Call with error immediately before returning from goroutine.
func (c *Collator) Failure(err error) {
c.errors <- err
c.wg.Done()
}
// Call immediately before returning from goroutine when a work item is determined by business logic should be skipped.
func (c *Collator) Skip() {
c.wg.Done()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment