英文:
How to handle errors in goroutines?
问题
我正在尝试同时运行多个任务,并获取结果或错误。
// 数据通道
ch := make(chan int)
ch2 := make(chan int)
ch3 := make(chan int)
// 错误通道
errCh := make(chan error)
errCh2 := make(chan error)
errCh3 := make(chan error)
// 启动任务
go taskF(ch, errCh)
go taskF2(ch2, errCh2)
go taskF3(ch3, errCh3)
然后我开始检查每个错误。如果有任何错误,我们打印它;否则,我们打印每个任务的结果。
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
}
然后,如果没有错误,我收集通过每个通道返回的值。
task := <-ch
task2 := <-ch2
task3 := <-ch3
print("task %v task2 %v task3 %v", task, task2, task3)
我想知道我是否做得对。我担心代码太冗长。我在考虑使用带缓冲的通道来处理错误,但我不知道如何检查所有的错误。我认为在goroutine中同步错误会很好,这样如果一个goroutine出现错误,其他goroutine就会停止,但我不知道如何以非阻塞的方式实现。
英文:
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.
答案1
得分: 1
考虑只使用一个通道进行同步,并且在该通道中包含一个错误状态(参见Result结构体)。每当接收到一个Result时,确保错误状态为nil。将每个任务封装在一个Task结构体中,这样当一个任务返回错误时,可以调用每个任务的Stop方法。根据您的具体应用程序,可能有更好的处理方式,比如使用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) {
// 长时间运行的任务在这里
// 定期检查t.stopped
doneChan <- Result{Val: ..., Err: nil}
}
英文:
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}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论