The user with no hat
The user with no hat

Reputation: 10856

How to handle errors in goroutines?

I'm trying to run several tasks concurrently and get the result or error back.

//data channels
    ch := make(chan int)
    ch2 := make(chan int)
    ch2 := make(chan int)
//error channels 

   errCh := make(chan error)
    errCh2 := make(chan error)
    errCh3 := make(chan error)

 //functions 
        go taskF(ch, errCh)
        go taskF2(ch2, errCh2)
        go taskF3(ch3, errCh3)

Then I start checking on each error. If there is any error we print it otherwise we print the result of each task

      err := <-errCh
      if err != nil{
           print('we have an error ')
       return  
  }
          err2 := <-errCh2
          if err2 != nil{
           print('we have an error 2')
           return  
  }
       err3 := <-errCh3
      if err3!= nil{
           print('we have an error 3')
           return   
 }

Then if there is no error I collect the values returned though each channel

task := <-ch
task2 := <-ch2
task3 := <-ch3

print("task %v task2 %v task3 %v", task, task2, task3)

I'm wondering if I'm doing it right. I'm worried that the code quite verbose. I was thinking to use buffered channels for errors but i can't figure it out how to check all the errors. I think it would also be nice to somehow sync the errors within the goroutines so that if there is an error on one goroutine the other goroutines would stop but I don't know any way to do in an unblocking manner.

Upvotes: 4

Views: 5437

Answers (1)

Kevin King
Kevin King

Reputation: 1559

Consider using only one channel for synchronization, and having this channel include an error state (see the Result struct). Whenever you receive a Result, make sure the error state is nil. Wrapping each task in a Task struct will allow you to call Stop on each task when one returns an error. Depending on your exact application there may be better ways to handle this, such as WaitGroups (http://golang.org/pkg/sync/#WaitGroup).

type Result struct {
    Val int
    Err error
}
type Task struct {
     stopped bool
}

func (t *Task) Stop() {
     t.stopped = true
}
func (t *Task) Run(doneChan chan Result) {
    // long-running task here
    // periodically check t.stopped
    doneChan <- Result{Val: ..., Err: nil}
}

Upvotes: 1

Related Questions