Урок объясняет, что такое каналы в Go, как передавать данные между горутинами, различия между буферизированными и небуферизированными каналами, работу с select, таймауты и создание однонаправленных каналов.
Каналы - это механизм связи между горутинами, позволяющий безопасно передавать данные, синхронизировать выполнение и строить конкурентный код без гонок данных.
ch := make(chan int)
Так создаётся небуферизированный канал, который блокирует отправителя до момента чтения.
go func() { ch <- 1 }()
value := <-ch
fmt.Println(value) // 1
ch <- x - отправка данных<-ch - получение данныхch := make(chan int)
go func() { ch <- 1 }()
go func() { ch <- 2 }()
go func() { ch <- 3 }()
a := <-ch
b := <-ch
c := <-ch
fmt.Println(a, b, c)
Порядок зависит от планировщика.
Буфер позволяет отправлять данные без немедленного чтения:
ch := make(chan int, 2)
ch <- 1
ch <- 2
go func() { ch <- 3 }()
fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2
fmt.Println(<-ch) // 3
Поведение - FIFO.
Можно ограничить направление:
func worker(in <-chan int, out chan<- int) {
x := <-in
out <- x * 2
}
<-chan - только чтениеchan<- - только записьselect даёт возможность слушать несколько каналов:
one := make(chan int)
two := make(chan int)
for {
select {
case o := <-one:
fmt.Println("one:", o)
case t := <-two:
fmt.Println("two:", t)
default:
fmt.Println("no data")
time.Sleep(50 * time.Millisecond)
}
}
ch := make(chan int)
for {
select {
case v := <-ch:
fmt.Println("received:", v)
case <-time.After(300 * time.Millisecond):
fmt.Println("timed out")
return
}
}