2015-04-18 3 views
3

У меня есть канал, называемый queue, скажем 100 в качестве размера буфера. Многие из подпрограмм могут отправлять данные на этот канал, а другая процедура идет, чтобы получать данные с этого канала. Это длительный процесс, означающий, что канал действует как трубопровод, поглощающий данные со многих концов и погружающие данные в один конец. Я делаю что-то вроде этого в приемной идти рутину:Параллельный канал передачи/приема go

for { 
    for data := range queue { 
     sink(data) 
    } 
} 

Теперь мой вопрос: что если какие-то новые данные были отправлены в буфер канала до контура диапазона закончен. Будут ли новые данные доступны для следующего цикла диапазона? Или они будут упущены, если параллелизм не будет принят во внимание в этом случае?

+0

На ваш вопрос из [спецификации по типу чан] (http://golang.org/ref/spec#Channel_types): Один канал может использоваться в операторах посыла , операции приема и вызовы встроенных функций cap и len с помощью любого количества goroutines без дальнейшей синхронизации. Так что ничего не будет потеряно – IamNaN

ответ

4

Вам нужен только один цикл for. От spec on range expressions::

Для каналов значениями итераций являются последовательные значения, посылаемые по каналу до тех пор, пока канал не будет закрыт. Если канал равен nil, диапазон выражения блокирует навсегда.

В этом случае цикл диапазона не действует как обычный диапазон, например, срез. Вместо этого, когда элемент может быть прочитан из канала, тело цикла обрабатывает его. Таким образом, ваши вложенные циклы должны быть заменены на следующие:

for data := range queue { 
    sink(data) 
} 
+0

Ага, я понял. Это полностью очистило мой вопрос. Спасибо. –

3

Как @Tim сказал, вам нужно всего лишь один for, поскольку range будет излучать значения из канала, пока он не будет закрыт.

В целом, шаблон, который вы описываете, называется fan-in. Пример базовой настройки производителя/потребителя можно найти здесь: http://play.golang.org/p/AhQ012Qpwj. Петля диапазон работает в потребителе:

// consumer acts as fan in, signals when it is done. 
func consumer(out chan string, done chan bool) { 
    for value := range out { 
     fmt.Println(value) 
    } 
    done <- true 
} 
+1

Процесс встраивания также известен как мультиплексор, потому что сообщения должны быть мультиплексированы, то есть чередуются в последовательный порядок. Поскольку приход сообщений в канал является параллельным, порядок, в котором они чередуются, является произвольным и приближается к первому. –

+0

Спасибо. Это действительно преимущество «Голанга», которое неудобно, или, по крайней мере, склонность к внедрению на других языках. –

Смежные вопросы