去等待 goroutines 但同时做一些事情
Go wait for goroutines but do stuff in the meantime
我有以下代码:
func execTask(input int, results chan<- int) {
//do stuff (in my case, start process and return something)
results <- someResult
}
func main() {
results := make(chan int)
for _, task := range tasks {
go execTask(task, results)
}
for result := range results {
fmt.Println(result)
}
}
对于行 for result := range results {
我得到一个错误:
fatal error: all goroutines are asleep - deadlock!
。在例程execTask
中我实际上执行了一个过程os/exec,所以我不知道results
中有多少结果。所以我必须等待我所有的过程完成,但与此同时对结果做一些事情。当所有进程终止时,我的 go-Programm 也可能终止。
我该怎么做?
谢谢,
拉斯
您收到死锁错误是因为您没有关闭 results
频道。因此,main
继续等待 results
上的更多数据,即使在所有 execTask
都已完成之后,也没有其他内容写入 results
.
您可以使用 sync.WaitGroup
:
来解决这个问题
func main() {
var wg sync.WaitGroup
results := make(chan int)
wg.Add(len(tasks))
for _, task := range tasks {
go func(task int) {
defer wg.Done()
execTask(task, results)
}(task)
}
go func() {
wg.Wait() // wait for each execTask to return
close(results) // then close the results channel
}
for result := range results {
fmt.Println(result)
}
}
至于在其他进程仍在执行的同时处理 execTask
结果,您已经有了正确的想法。只需在 results
范围循环中处理它们。如果你想要更多的并发执行,可以在那里启动更多的 goroutines。
我有以下代码:
func execTask(input int, results chan<- int) {
//do stuff (in my case, start process and return something)
results <- someResult
}
func main() {
results := make(chan int)
for _, task := range tasks {
go execTask(task, results)
}
for result := range results {
fmt.Println(result)
}
}
对于行 for result := range results {
我得到一个错误:
fatal error: all goroutines are asleep - deadlock!
。在例程execTask
中我实际上执行了一个过程os/exec,所以我不知道results
中有多少结果。所以我必须等待我所有的过程完成,但与此同时对结果做一些事情。当所有进程终止时,我的 go-Programm 也可能终止。
我该怎么做?
谢谢, 拉斯
您收到死锁错误是因为您没有关闭 results
频道。因此,main
继续等待 results
上的更多数据,即使在所有 execTask
都已完成之后,也没有其他内容写入 results
.
您可以使用 sync.WaitGroup
:
func main() {
var wg sync.WaitGroup
results := make(chan int)
wg.Add(len(tasks))
for _, task := range tasks {
go func(task int) {
defer wg.Done()
execTask(task, results)
}(task)
}
go func() {
wg.Wait() // wait for each execTask to return
close(results) // then close the results channel
}
for result := range results {
fmt.Println(result)
}
}
至于在其他进程仍在执行的同时处理 execTask
结果,您已经有了正确的想法。只需在 results
范围循环中处理它们。如果你想要更多的并发执行,可以在那里启动更多的 goroutines。