玩转 go,我把这段代码放在一起:package mainimport "fmt"const N = 10func main() { ch := make(chan int, N) done := make(chan bool) for i := 0; i < N; i++ { go (func(n int, ch chan int, done chan bool) { for i := 0; i < N; i++ { ch <- n*N + i } done <- true })(i, ch, done) } numDone := 0 for numDone < N { select { case i := <-ch: fmt.Println(i) case <-done: numDone++ } } for { select { case i := <-ch: fmt.Println(i) default: return } }}基本上我有 N 个频道在做一些工作并在同一个频道上报告——我想知道所有频道什么时候完成。所以我有另一个done通道,每个工作程序 goroutine 都会在其上发送一条消息(消息无关紧要),这会导致 main 将该线程计为已完成。当计数达到 N 时,我们实际上就完成了。这是“好”吗?有没有更惯用的方式来做到这一点?编辑:澄清一下,我很怀疑,因为done通道似乎正在做一个通道关闭似乎是为了的工作,但当然我实际上不能在任何 goroutine 中关闭通道,因为所有的例程共享同一个通道. 所以我done用来模拟一个执行某种“缓冲关闭”的通道。编辑2:原始代码并没有真正起作用,因为有时在done它刚刚放入的 int 之前读取来自例程的信号ch。需要一个“清理”循环。
3 回答
海绵宝宝撒
TA贡献1809条经验 获得超8个赞
这里是sync.WaitGroup的惯用用法,供大家学习
package main
import (
"fmt"
"sync"
)
const N = 10
func main() {
ch := make(chan int, N)
var wg sync.WaitGroup
for i := 0; i < N; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
for i := 0; i < N; i++ {
ch <- n*N + i
}
}(i)
}
go func() {
wg.Wait()
close(ch)
}()
for i := range ch {
fmt.Println(i)
}
}
注意两个go例程定义中闭包的使用,注意第二条go语句等待所有例程完成,然后关闭通道,所以range可以使用。
- 3 回答
- 0 关注
- 224 浏览
添加回答
举报
0/150
提交
取消