【发布时间】:2016-04-22 05:55:27
【问题描述】:
我是围棋学习者。为了更好地理解 channel 和 goroutines 的关心和馈送,我正在尝试构建一个 Sieve of Eratosthenes 作为一组 goroutines 通过 channel 连接到管道中。
这是我目前所拥有的:
// esieve implements a Sieve of Eratosthenes
// as a series of channels connected together
// by goroutines
package main
import "fmt"
func sieve(mine int, inch chan int) {
start := true // First-number switch
ouch := make(chan int) // Output channel for this instance
fmt.Printf("%v\n", mine) // Print this instance's prime
for next := <-inch; next > 0; next = <-inch { // Read input channel
fmt.Printf("%v <- %v\n",mine,next) // (Trace)
if (next % mine) > 0 { // Divisible by my prime?
if start { // No; is it the first number through?
go sieve(next, ouch) // First number - create instance for it
start = false // First time done
} else { // Not first time
ouch <- next // Pass it to the next instance
}
}
}
}
func main() {
lim := 30 // Let's do up to 30
fmt.Printf("%v\n", 2) // Treat 2 as a special case
ouch := make(chan int) // Create the first segment of the pipe
go sieve(3, ouch) // Create the instance for '3'
for prime := 3; prime < lim; prime += 2 { // Generate 3, 5, ...
fmt.Printf("Send %v\n", prime) // Trace
ouch <- prime // Send it down the pipe
}
}
就它而言,它工作得很好。
但是,当我完成主循环时,main 会在仍处于 sieve 实例管道中的所有数字传播到末尾之前退出。
让主例程等待一组 goroutines(它只“知道”第一个)完成的最简单、最优雅或普遍接受的方法是什么?
【问题讨论】:
-
最简单且推荐的解决方案是使用
main将阻塞的另一个通道并接收操作结果。 -
@icza :我部分同意;该问题涉及更简单的(星型)拓扑。在我的情况下,只有管道中的最后一个 goroutine 必须发出关闭信号,一旦它知道它是最后一个。我想我已经接近最终答案了,我最终会在这里发布。顺便说一句,使用令人愉快的构造!
-
@creker:谢谢。这有助于我了解我必须如何解决问题,所以如果你愿意发布作为答案,我会接受。我还计划将结果发布为我自己的答案。