2014-08-28 3 views
1

Это является примером простого числа просеятьКак работают каналы в этом примере?

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 
    } 
} 

То, что я понимаю, эта строка кода

prime := <-ch 

канал ждет ввода и назначает премьер. Итак, почему же все числа не печатаются, когда следующий оператор называется

print(prime, "\n") 

Если удалить эти последние 3 строки

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

тогда все числа напечатанных от 2 до 11. Что делает эту линию do ch = ch1?

Благодаря

+1

Контекст: http://golang.org/doc/play/sieve.go. Также оптимизирован в http://blog.onideas.ws/eratosthenes.go – VonC

+0

@ VonC благодарит за ссылку.в цитированной статье отсутствует идея «отсрочки» (http://stackoverflow.com/a/8871918/849891) - промежуточного, но значимого шага улучшения. Другая важная оптимизация (связанная с отсрочкой, на самом деле) - [сокращение хранения памяти] (http://stackoverflow.com/a/13895347/849891), открывая цикл обратной связи (что упоминается в блоге). Это позволяет иметь башню первичных каналов, каждая с небольшим буфером (версия python [здесь] (http://stackoverflow.com/a/10733621/849891) - см. Четвертую строку в коде). –

+0

@WillNess выглядит действительно на первый взгляд. – VonC

ответ

2

выхода Вашего кода является:

2 
3 
5 
7 
11 
13 
17 
19 
23 
29 

Так процедура выглядит так:

я = 0,

после prime := <-ch, prime = 2, ch = {3};

после go Filter(ch, ch1, prime), пометить как Filter0, в функции Filter0 канала in будет 3,4,5,6 ... и канал out будет 3,5,7 ...;

После ch = ch1, так что ch = {3}, что будет 3,5,7.

= 1,

после prime := <-ch, простое = 3, CH = {5}, почему там в ch5 Потому что в настоящее время ch в последнем цикле ch1;

после go Filter(ch, ch1, prime), пометить как Filter1, в функции Filter1 канала in будет 5,7,9,11 ... и канал out будет 5,7,11 ...;

После ch = ch1, так что ch = {3}, что будет 5,7,11.

i = 2, то же самое.

Это как выход.

1

Причина не все числа печатаются, потому что это не тот же самый канал в каждой итерации цикла. Он создает новый канал ch1 и фильтрует значения из ch в ch1, а затем назначает ch ch1, так что следующая итерация ch является новым каналом от предыдущей итерации (там называется ch1), а значения там фильтруются фильтром goroutine.

Вот еще один способ, чтобы написать его, что может сделать больше смысла для вас:

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 
} 
Смежные вопросы