1

This is is an example of prime number sieve

package main

func Generate(ch chan<- int) {
  for i := 2; ; i++ {
    ch <- i
  }
}

func Filter(in <-chan int, out chan<- int, prime int) {
  for {
    i := <-in
    if i%prime != 0 {
      out <- i
    }
  }
}

func main() {
  ch := make(chan int)
  go Generate(ch)
  for i := 0; i < 10; i++ {
    prime := <-ch
    print(prime, "\n")
    ch1 := make(chan int)
    go Filter(ch, ch1, prime)
    ch = ch1
  }
}

What I understand is this line of code

prime := <-ch

the channel is waiting for an input and assigns to prime. So, why all the numbers are not printed when the next statement is called

print(prime, "\n")

If I remove these last 3 lines

ch1 := make(chan int)
go Filter(ch, ch1, prime)
ch = ch1

then all numbers are printed from 2 to 11. What does this line do ch = ch1?

Thanks

Will Ness
  • 62,652
  • 8
  • 86
  • 167
John
  • 2,781
  • 2
  • 16
  • 25
  • 1
    Context: http://golang.org/doc/play/sieve.go. Also optimized in http://blog.onideas.ws/eratosthenes.go – VonC Aug 28 '14 at 12:50
  • @VonC thanks for the link. the article cited lacks the idea of [postponement](http://stackoverflow.com/a/8871918/849891) - an intermediate yet significant improvement step. Another important optimization (related to postponement, really) is [reducing memory retention](http://stackoverflow.com/a/13895347/849891) by breaking open the feedback loop (that the blog mentions). This makes possible to have a tower of prime-producing channels, each with only a small buffer (python version [here](http://stackoverflow.com/a/10733621/849891) - see the 4th line in the code). – Will Ness Oct 01 '14 at 00:26
  • @WillNess looks good indeed at first glance. – VonC Oct 01 '14 at 08:08
  • here's [the working code on ideone](http://ideone.com/RPwHJe). – Will Ness Oct 01 '14 at 13:02

2 Answers2

3

Your code's output is :

2
3
5
7
11
13
17
19
23
29

So the procedure is like this :

i=0,

after prime := <-ch , prime=2, ch = {3};

after go Filter(ch, ch1, prime) , mark as Filter0,in function Filter0 channel in will be 3,4,5,6 ... and channel out will be 3,5,7 ...;

After ch = ch1, So ch = {3}, which will be 3,5,7.

i=1,

after prime := <-ch ,prime= 3, ch ={5},why is there 5 in ch?'Cause now ch is the ch1 in last loop ;

after go Filter(ch, ch1, prime) , mark as Filter1,in function Filter1 channel in will be 5,7,9,11 ... and channel out will be 5,7,11 ...;

After ch = ch1, So ch = {3}, which will be 5,7,11.

i=2, the same .

That how it output.

frank.lin
  • 1,466
  • 15
  • 23
1

The reason not all numbers are printed is because it's not the same channel in each iteration of the loop. It creates a new channel ch1 and filters values from ch into ch1 and then it assigns ch to ch1 so that the next iteration ch is the new channel from the previous iteration (there known as ch1) and the values there have been filtered by the Filter goroutine.

Here is another way to write it that may make more sense to you:

for i := 0; i < 10; i++ {
    prime := <-ch
    print(prime, "\n")
    oldch := ch          //here oldch references the old channel
    ch = make(chan int)  //and here ch is replaced with a new channel
    go Filter(oldch, ch, prime) //and here a filter is applied to values from oldch to ch
}
Brainstorm
  • 950
  • 7
  • 13