我试图按照http://blog.golang.org/pipelines/bounded.go发布的有限goroutine示例进行操作。我遇到的问题是,如果有更多的工作人员开始工作,那么额外的工作人员永远不会被取消。其他一切似乎都有效,价值得到计算和记录,但当我关闭groups
频道时,工作人员只是挂在范围声明中。
我想我不明白(在我的代码和示例代码中)工作人员如何知道什么时候没有更多的工作要做,他们应该退出?
更新
在http://play.golang.org/p/T7zBCYLECp张贴了一个工作(即非工作)的例子。它显示了工人的僵局,因为他们都睡着了,没有工作要做。我感到困惑的是,我认为示例代码会遇到同样的问题。
以下是我目前正在使用的代码:
// Creates a pool of workers to do a bunch of computations
func computeAll() error {
done := make(chan struct{})
defer close(done)
groups, errc := findGroups(done)
// start a fixed number of goroutines to schedule with
const numComputers = 20
c := make(chan result)
var wg sync.WaitGroup
wg.Add(numComputers)
for i := 0; i < numComputers; i++ {
go func() {
compute(done, groups, c)
wg.Done()
}()
}
go func() {
wg.Wait()
close(c)
}()
// log the results of the computation
for r := range c { // log the results }
if err := <-errc; err != nil {
return err
}
return nil
}
以下是用数据填充频道的代码:
// Retrieves the groups of data the must be computed
func findGroups(done <-chan struct{}) (<-chan model, <-chan error) {
groups := make(chan model)
errc := make(chan error, 1)
go func() {
// close the groups channel after find returns
defer close(groups)
group, err := //... code to get the group ...
if err == nil {
// add the group to the channel
select {
case groups <- group:
}
}
}()
return groups, errc
}
这是读取通道进行计算的代码。
// Computes the results for the groups of data
func compute(done <-chan struct{}, groups <-chan model, c chan<- result) {
for group := range groups {
value := compute(group)
select {
case c <- result{value}:
case <-done:
return
}
}
}
答案 0 :(得分:2)
因为你试图从errc
读取,除非出现错误,否则它是空的。
//修改
如果没有错误, computeAll()
将始终阻止<- errc
,另一种方法是使用以下内容:
func computeAll() (err error) {
.........
select {
case err = <-errc:
default: //don't block
}
return
}
答案 1 :(得分:1)
尝试关闭errc,因为OneOfOne说
go func() {
wg.Wait()
close(c)
close(errc)
}()
// log the results of the computation
for r := range c { // log the results }
if err := range errc {
if err != nil {
return err
}
}