В Go существует два основных способа взаимодействия с каналами:
ch <- data // запись данных в канал
value := <-ch // чтение данных из канала
ch := make(chan int)
go func() {
ch <- 42 // записываем значение в канал
}()
Для небуферизированных каналов:
Для буферизированных каналов:
Попытка записи в закрытый канал вызывает panic:
close(ch)
ch <- 42 // panic: send on closed channel
value := <-ch // чтение из канала в переменную
x := <-ch
value, ok := <-ch
if !ok {
// канал закрыт и пуст
}
for item := range ch {
// обработка item
// цикл завершится автоматически при закрытии канала
}
func main() {
ch := make(chan string)
go func() {
ch <- "Hello, World!" // запись
}()
msg := <-ch // чтение
fmt.Println(msg)
}
func main() {
ch := make(chan int, 2)
ch <- 1 // не блокируется
ch <- 2 // не блокируется
// ch <- 3 // заблокировалось бы (буфер полон)
fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2
}
func producer(ch chan<- int) {
for i := 0; i < 3; i++ {
ch <- i
}
close(ch) // важно закрыть для правильной работы range
}
func consumer(ch <-chan int) {
for n := range ch {
fmt.Println("Received:", n)
}
}
ch := make(chan int)
<-ch // вечная блокировка - нет писателя
// или
ch <- 42 // вечная блокировка - нет читателя
Паника при записи в закрытый канал
Утечка горутин из-за незакрытых каналов
select {
case msg := <-ch1:
fmt.Println(msg)
case ch2 <- 42:
fmt.Println("sent")
default:
fmt.Println("no activity")
}
select {
case res := <-ch:
fmt.Println(res)
case <-time.After(1 * time.Second):
fmt.Println("timeout")
}
done := make(chan struct{})
close(done) // сигнал закрытия
ch <- data
, чтение: data := <-ch