Канал в Go – это способ объявить канал связи между запущенными проектами
Для объявления канала мы можем просто использовать msg := make(chan string)
, а для передачи сообщений в него мы можем использовать оператор <-
, так например msg <- "hello"
передает значение “hello” в канал msg
и для получения этого значения из канала мы также используем тот же оператор, так что это будет например result := <-msg
.
func main() {
msg := make(chan string)
go func() {
msg <- "Hello World"
}()
result := <-msg
fmt.Println(result)
}
Эта главная функция при выполнении будет писать “Hello World” в консоль
ps: канал может получить новое значение только после “опустошения”, опустошение канала – это как я делаю, когда присваиваю его значение результату
Общение между рутинами
Как я уже говорил, канал – это способ коммуникации между рутинами. Это можно продемонстрировать следующим образом
func main() {
channel := make(chan int)
go func() {
for i := 0; i < 10; i++ {
channel <- i
}
}()
go func() {
for {
fmt.Println(<-channel)
}
}()
time.Sleep(time.Second)
}
В этом случае мы не только передаем значение от одной функции к другой без возникновения условий гонки, но и имеем зависимость между функциями, поскольку первая функция может продолжать присваивать значение каналу только после его опустошения, а вторая функция отвечает за его опустошение.
Это как эстафета, где одно зависит от другого, в данном случае в беге бегуну нужно, чтобы его партнер добрался до него, а в канале первой функции нужно, чтобы канал опустел
ps: не забывайте использовать close(channel)
после завершения использования канала
Тупик
Тупик возникает, когда мы создаем канал и присваиваем ему значение без выполнения канала в рамках процедуры go.
func main() {
channel := make(chan int)
// channel <- 10 DEADLOCK !!
go func() {
channel <- 10
}()
fmt.Println(<-channel)
}