Как работают каналы в этом примере?

Это пример решета простых чисел

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. Что делает эта строка ch = ch1?

Спасибо


person John    schedule 28.08.2014    source источник
comment
Контекст: golang.org/doc/play/sieve.go. Также оптимизировано в blog.onideas.ws/eratosthenes.go   -  person VonC    schedule 28.08.2014
comment
@VonC спасибо за ссылку. в цитируемой статье отсутствует идея отсрочки - промежуточного, но значительного шага улучшения. Еще одна важная оптимизация (на самом деле связанная с отсрочкой) — это уменьшение удержания памяти за счет разрыва цикла обратной связи (о котором упоминается в блоге) . Это позволяет иметь башню основных производящих каналов, каждый с небольшим буфером (версия Python здесь - см. 4-я строка кода).   -  person Will Ness    schedule 01.10.2014
comment
@WillNess действительно хорошо выглядит на первый взгляд.   -  person VonC    schedule 01.10.2014
comment
вот рабочий код на ideone.   -  person Will Ness    schedule 01.10.2014


Ответы (2)


Вывод вашего кода:

2
3
5
7
11
13
17
19
23
29

Итак, процедура такова:

i=0,

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

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

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

i=1,

после prime := <-ch ,prime= 3, ch ={5}, почему 5 в ch? Потому что теперь ch это ch1 в последнем цикле;

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

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

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

Вот как это выводится.

person frank.lin    schedule 29.08.2014

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

Вот еще один способ написать это, который может иметь для вас больше смысла:

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
}
person Brainstorm    schedule 28.08.2014