Передача потоков данных

Последнее обновление: 12.01.2018

Нередко одна горутина транслирует другой горутине через канал не одиночные значения, а некоторый поток данных. В этом случае общий алгоритм состоит в том, что горутина-отправитель в течение некоторого периода отправляет данные. Когда данные для отправки закончились, работа сделала, отправитель закрывает канал.

Горутина-получатель в бесконечном цикле получает данные из канала. Если будет получен маркер закрытия канала, то осуществляется выход из бесконечного цикла.

package main
import "fmt"

func main(){
   intCh := make(chan int) 
   
   go factorial(7, intCh)
 
   for { 
         num, opened := <- intCh 	// получаем данные из потока
         if !opened { 
               break 	// если поток закрыт, выход из цикла
         } 
         fmt.Println(num)
   }
}

func factorial(n int, ch chan int){
	defer close(ch)
	result := 1
	for i := 1; i <= n; i++{
		result *= i
		ch <- result		// посылаем по числу
	}
}

В данном случае функция main и горутина factorial взаимодействуют через канал intCh. Функция factorial последовательно вычисляем факториалы чисел от 1 до n. И все вычисленные значения передаются в канал. По завершении функции factorial канал закрывается вызывом defer close(ch).

В функции main в бесконечом цикле отправленные данные извлекаются из канала. При этом также проверяется, открыт ли канал. И ели вдруг канал закрыт и соответственно нет смысла получать из него данные, происходит выход из бесконечного цикла:

for { 
	num, opened := <- intCh 
	if !opened { 
		break 
	} 
	fmt.Println(num)
}

Консольный вывод программы:

1
2
6
24
120
720
5040

При извлечении значений из канала мы можем использовать ту же форму цикла for, которая применяется для перебора коллекций:

for переменная := канал{
	//...........
}

Например, перепишем предыдущий пример:

package main
import "fmt"

func main(){
   intCh := make(chan int) 
   
   go factorial(7, intCh)
 
	for num := range intCh{
		fmt.Println(num)
	}
}

func factorial(n int, ch chan int){
	defer close(ch)
	result := 1
	for i := 1; i <= n; i++{
		result *= i
		ch <- result
	}
}

Когда канал будет закрыт, то автоматически произойдет выход из цикла for.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850