← Назад

Каналы в Go

Канал (channel) — это типизированная очередь, через которую горутины могут безопасно передавать данные.

Простыми словами: канал можно представить как безопасную очередь, в которую одна горутина кладёт данные, а другая — забирает.

Базовые действия:

go
// создание канала
ch := make(chan int)

// операции
ch <- 10  // отправка в канал
x := <-ch  // получение из канала

Виды каналов

  1. Буферизированные
  2. Небуферизированные

Рассмотрим каждый канал по отдельности. Начнем с небуферизированного канала.

Небуферизированные каналы

Как их создать — уже рассмотрели наверху. Какие у них особенности?

  • не имеют внутреннего хранилища (буфера)
  • отправка блокируется, пока значение не будет прочитано
  • обеспечивают строгую синхронизацию между горутинами

Используются по умолчанию и подходят в большинстве случаев.

Буферизованные каналы

От небуферизированных они отличаются только тем, что у них есть буфер. И только. Пример создания:

go
// создание канала
ch := make(chan int, 3)
// 3 - буфер из 3х элементов
  • имеют буфер фиксированного размера (в нашем случае — 3)
  • позволяют отправлять данные, пока буфер не заполнен (т.е. отправители не будут блокироваться до тех пор, пока буфер не переполнится).
  • уменьшают жёсткую зависимость между отправителем и получателем

Полезны, когда скорость работы горутин отличается.

Примеры

Небуферизированный канал

go
ch := make(chan string)

go func() {
    ch <- "Сообщение из горутины"
}()

fmt.Println(<-ch)

Здесь мы создали канал, в который кладем текстовое значение "Сообщение из горутины" и читаем в основной горутине (main) командой <-ch. Основная горутина будет ждать, пока дочерняя отправит сообщение.

Буферизованный канал

go
ch := make(chan int, 2)

ch <- 1
ch <- 2

fmt.Println(<-ch)
fmt.Println(<-ch)

Создали канал с буфером == 2. Если придут 3 горутины, которые хотят положить данные в этот канал, то первые две положат в него данные, а 3-я будет заморожена, пока буфер не освободится (т.е. пока читатель не прочитатет оттуда какое-то значение, чтобы ячейа буфера освободилась, чтобы 3-я горутина смогла положить туда свои данные).

Сигнал о завершении работы

go
done := make(chan struct{})

go func() {
    fmt.Println("Выполняю работу")
    done <- struct{}{}
}()

<-done
fmt.Println("Работа завершена")

Классический и очень популярный паттерн для ожидания завершения горутины. Примерно таким образом я использовал каналы взамен sync.Mutex, для своих учебных задач.

Итог

Каналы — основной способ общения между горутинами в Go. Чаще всего используются:

  • небуферизованные каналы — для синхронизации
  • буферизованные каналы — для асинхронной передачи данных

Данная статья не раскрывает полностью возможности и способы использования каналов в Go, а лишь описывает их поверхностно.

Похожие статьи

Quick Sort: быстрая сортировка

Сортировка — одна из базовых задач в программировании. Упорядоченные данные легче искать, сравнивать и обрабатывать. За десятилетия придумали десятки алгоритмов сортировки. У каждого свои сильные и слабые стороны. Сегодня рассмотрим Quick Sort,

09.04.2026 · 3 мин

Garbage Collector in Go

Garbage Collector (GC) или сборщик мусора - это автоматический менеджер памяти, встроенный в среду выполнения (runtime). Его основная задача - освободить разработчика от ручного управления памятью.

07.04.2026 · 3 мин

Односвязный список

Рассмотрим на практике что такое односвязный список, из чего он состоит и как работает...

07.04.2026 · 2 мин

Слайсы в Go. Советы

Краткие совету по тому, как пользоваться слайсами, а также про подводные камни...

07.04.2026 · 2 мин

Комментарии

0

Ты: ...

Пока нет комментариев. Будь первым.