Однонаправленный канал
Однонаправленный канал — это канал, у которого ограничено направление передачи данных. В Go мы можем объявить канал, который будет использоваться только для отправки значений (chan<-) или только для получения значений (<-chan). Это позволяет явно указать намерения разработчика и предотвратить случайные операции, которые могут привести к ошибкам. Обычно такие каналы используются в сигнатурах функций, чтобы показать, как именно функция взаимодействует с каналом.
Синтаксис
var sendOnly chan<- int // только для отправки
var recvOnly <-chan int // только для получения
Пример
Давайте создадим функцию, которая принимает однонаправленный канал для отправки данных. Внутри функции будем отправлять значения в канал, а в главной функции — считывать их. Это поможет понять, как ограничение направления работает на практике.
package main
import "fmt"
// Функция принимает канал только для отправки
func sendData(ch chan<- int) {
for i := 1; i <= 3; i++ {
ch <- i * 10
}
close(ch)
}
func main() {
ch := make(chan int)
go sendData(ch)
// Читаем данные из канала
for val := range ch {
fmt.Println(val)
}
}
Результат выполнения кода:
10
20
30
Пример
Теперь рассмотрим функцию, которая принимает канал только для получения данных и обрабатывает их. Это полезно, когда функция должна только читать значения из канала, не изменяя его состояние.
package main
import "fmt"
// Функция принимает канал только для получения
func processData(ch <-chan int) {
for val := range ch {
fmt.Printf("Received: %d\n", val)
}
}
func main() {
ch := make(chan int)
go func() {
for i := 1; i <= 3; i++ {
ch <- i * 5
}
close(ch)
}()
processData(ch)
}
Результат выполнения кода:
"Received: 5"
"Received: 10"
"Received: 15"
Пример
Однонаправленные каналы также можно создавать с буферизацией. Это работает точно так же, как и с обычными каналами: мы указываем размер буфера при создании, а направление ограничиваем при передаче.
package main
import "fmt"
func main() {
ch := make(chan string, 2)
// Отправляем данные в буферизированный канал
ch <- "a"
ch <- "b"
// Передаём канал в функцию только для получения
readChan := func(ch <-chan string) {
for val := range ch {
fmt.Println(val)
}
}
close(ch)
readChan(ch)
}
Результат выполнения кода:
"a"
"b"
Смотрите также
-
статью
каналы в Go,
которая описывает общие принципы работы с каналами -
статью
буферизированный канал,
которая объясняет особенности работы с буферизированными каналами -
статью
отправка данных в канал,
которая показывает, как отправлять значения в канал -
статью
получение данных из канала,
которая демонстрирует способы чтения из канала