玩弄 go,我把这段代码放在一起:
package main
import "fmt"
const N = 10
func 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
。需要一个“清理”循环。