Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package gopool
- import "sync"
- // GoPool is a pool of goroutines with error reporting.
- type GoPool struct {
- waitGroup sync.WaitGroup
- errors chan error
- }
- // New initializes a new GoPool.
- func New() *GoPool {
- return &GoPool{
- waitGroup: sync.WaitGroup{},
- errors: make(chan error),
- }
- }
- // Run runs the specified function in a goroutine, collecting any errors that might occur.
- func (p *GoPool) Run(goFuncs ...func() error) {
- p.waitGroup.Add(len(goFuncs))
- for _, goFunc := range goFuncs {
- goFunc := goFunc
- go func() {
- defer p.waitGroup.Done()
- err := goFunc()
- if err != nil {
- p.errors <- err
- }
- }()
- }
- }
- // Wait waits for all specified tasks in the GoPoo to complete, and returns any collected errors that occurred.
- func (p *GoPool) Wait() (errors []error) {
- go func() {
- p.waitGroup.Wait()
- close(p.errors)
- }()
- for err := range p.errors {
- errors = append(errors, err)
- }
- return errors
- }
- func DoThings() {
- var thingA int
- var thingB string
- var thingC *Thing
- pool := gopool.New()
- pool.Run(func() (err error) {
- thingA, err = FetchThingA()
- return err
- })
- pool.Run(func() (err error) {
- thingB = FetchThingB()
- return nil
- })
- pool.Run(func() (err error) {
- thingC, err = FetchThingC()
- return err
- })
- errs := pool.Wait()
- if len(errs) > 0 {
- // Handle errs
- }
- // Use each of the fetched things
- }
- toRun := []func() error{}
- toRun = append(toRun, func() error{fmt.Println("one"); return nil});
- ....
- errors := pool.Run(toRun...)
- // Run will run all the supplied functions in separate Go-routines, and return any errors in the resulting slice,
- // and also return a boolen ok indicator which will be true if all goroutines succeeded.
- func Run(toRun ...func() error) ([]error, bool) {
- count := len(toRun)
- var wg sync.WaitGroup
- wg.Add(count)
- errors := make([]error, count, count)
- ok := true
- for i, fn := range toRun {
- // create a closure for the error index and the function
- go func(index int, fn func() error) {
- defer wg.Done()
- errors[index] = fn()
- }(i, fn)
- }
- wg.Wait()
- for _, e := range errors {
- if e != nil {
- ok = false
- }
- }
- return errors, ok
- }
- func main() {
- runs := []func() error{}
- runs = append(runs, func() error {
- fmt.Println("one")
- return nil
- })
- runs = append(runs, func() error {
- fmt.Println("two")
- return nil
- })
- runs = append(runs, func() error {
- fmt.Println("three")
- return nil
- })
- fmt.Println("Run one")
- if errs, ok := Run(runs...); !ok {
- fmt.Printf("Some errors: %vn", errs)
- } else {
- fmt.Println("OK")
- }
- runs = append(runs, func() error {
- fmt.Println("fail")
- return errors.New("Failed")
- })
- fmt.Println("Run Two")
- if errs, ok := Run(runs...); !ok {
- fmt.Printf("Some errors: %vn", errs)
- } else {
- fmt.Println("OK")
- }
- }
Add Comment
Please, Sign In to add comment