Go - 如何知道输出通道何时完成

Yuv*_*val 3 concurrency input channel go output

我尝试遵循 Rob Pike 在演讲“并发不是并行性”中的例子,做了这样的事情:我启动了许多 go 例程,作为从输入通道读取数据的工作程序,执行一些处理,然后通过输出通道发送结果。

然后我启动另一个 go 例程,从某个源读取数据并通过工作人员的输入通道将其发送给工作人员。最后,我想迭代输出通道中的所有结果并用它们做一些事情。问题是,因为工作是在工作人员之间分配的,所以我不知道所有工作人员何时完成,因此我可以停止向输出通道询问更多结果,并且我的程序可以正常结束。

了解工作人员何时完成将结果发送到输出通道的最佳实践是什么?

Not*_*fer 5

我个人喜欢使用 async.WaitGroup来实现这一点。waitgroup 是一个同步计数器,具有三个方法 - Wait()Done()Add()。您要做的就是增加等待组的计数器,将其传递给工作人员,并让他们Done()在完成后调用。然后,您只需阻塞另一端的等待组,并在全部完成后关闭输出通道,从而导致输出处理器退出。

基本上:

// create the wait group
wg := sync.WaitGroup{}

// this is the output channel
outchan := make(chan whatever)

// start the workers
for i := 0; i < N; i++ {
   wg.Add(1) //we increment by one the waitgroup's count

   //the worker pushes data onto the output channel and calls wg.Done() when done
   go work(&wg, outchan)
}

// this is our "waiter" - it blocks until all workers are done and closes the channel
go func() {
  wg.Wait()
  close(outchan)
}()

//this loop will exit automatically when outchan is closed
for item := range outchan {
   workWithIt(item)
}

// TADA!
Run Code Online (Sandbox Code Playgroud)