// generates numbers up to the given limit and writes them to a channel, closing the channel when finished
func generate(limit int, ch chan<- int) {
defer close(ch)
for i := 2; i < limit; i++ {
ch <- i
}
}
// receives numbers from a channel and filters for only those not divisible by the given
// divisor, writing to a destination channel and closing the destination when the src is closed
func filter(src <-chan int, dst chan<- int, divisor int) {
defer close(dst)
for i := range src { // Will block until a value is added to src, and break when src is closed
if i%divisor != 0 {
dst <- i
}
}
}
// prime sieving function
func sieve(limit int) {
ch := make(chan int)
go generate(limit, ch) // kicks off generator
for {
prime, ok := <-ch
if !ok {
break // we are done
}
// makes a new filter for the prime that was just seen, then adds it to the chain of running filters
newFilterChan := make(chan int)
go filter(ch, newFilterChan, prime)
ch = newFilterChan
fmt.Print(prime, " ")
}
}
func main() {
sieve(1000)
}