我需要同时处理几个任务,然后收集"结果。下面是我提出的代码,但我想知道它是否是正确的方法(即惯用/最佳实践),或者如果有什么不对的话我可能会错过。
package main
import "fmt"
import "sync"
func main() {
// ch is the int provider. Cap is 99 but it should
// really be 3
ch := make(chan int, 99)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
ch <- i
}(i)
}
wg.Wait()
for v := range ch {
fmt.Println("consume ", v)
if len(ch) == 0 {
close(ch)
}
}
fmt.Printf("All done")
}
答案 0 :(得分:1)
没有什么错误与...它的工作原理。但是,关闭渠道(而不是消费者)确实应该是生产者的工作。
为此...我建议你将整个制作人流程移动到goroutine并等待..然后关闭频道:
package main
import "fmt"
import "sync"
func main() {
ch := make(chan int, 3)
var wg sync.WaitGroup
go func() {
for i := 0; i < 3; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
ch <- i
}(i)
}
wg.Wait()
close(ch) // producer is now closing the channel
}()
// Consumer has the single responsibility of iterating over the channel
for v := range ch {
fmt.Println("consume ", v)
}
fmt.Printf("All done")
}
答案 1 :(得分:0)
我确信你的例子是人为的,但你的例子可以简单得多:
ch := make(chan int, 99)
for i := 0; i < 3; i++ {
go func(i int) {
ch <- i
}(i)
}
for i := 0; i < 3; i++ {
v := <- ch
fmt.Println("consume ", v)
}
fmt.Println("All done")
您的真实代码可能更复杂,需要像waitGroup这样的东西,如果是这种情况,请尽你所能来解释您的具体问题。
关闭一个范围内的频道以退出该范围似乎是非惯用的Go。