Гайды

Go: горутины и каналы

Планировщик и GOMAXPROCS, буферизованные каналы, select, sync и context, гонки и pprof.

~11 мин чтения

Go: горутины и каналы

Горутины — лёгкие потоки выполнения под управлением runtime Go; каналы (chan) передают данные и синхронизируют. Девиз: «Не общайтесь разделяя память; разделяйте память общаясь через каналы» — ориентир, не догма. Веб-сервисы на Go — Gin и Fiber.


1. Запуск горутины

go
go func() { fmt.Println("async") }()

Планировщик m:n мультиплексирует горутины на OS threads (GOMAXPROCS).


2. Каналы

go
ch := make(chan int, 2) // буфер 2
ch <- 1
v := <-ch
close(ch)

range по каналу до close. Закрывает только отправитель.


3. select

Мультиплексирование ожидания нескольких каналов + default для неблокирующего поведения.

go
// import "time"
select {
case msg := <-ch:
    fmt.Println("received", msg)
case <-time.After(time.Second):
    fmt.Println("timeout")
default:
    fmt.Println("no message ready")
}

Типичный паттерн завершения: case <-ctx.Done(): return ctx.Err() рядом с рабочими каналами, чтобы горутина не зависла после отмены контекста.


4. sync примитивы

WaitGroup, Mutex, Once, context.Context для отмены и дедлайнов в цепочке вызовов.


5. Антипаттерны

  • Гонки данных — go test -race.
  • Утечка горутин на блокирующем send без получателя.
  • Busy loop без select/sleep.

6. Пул воркеров и errgroup

Фиксированное число горутин читает задания из канала-очереди — предсказуемая нагрузка на CPU и сокеты. Пакет golang.org/x/sync/errgroup связывает отмену и первую ошибку между подзадачами; передавайте context из группы вниз по вызовам.


7. Graceful shutdown

На SIGINT/SIGTERM закройте приём новых запросов, отмените context, дождитесь WaitGroup воркеров с таймаутом. Каналы завершения: закрыть входную очередь после дренажа или использовать context.Done() в select отправителей.


8. Чек-лист

  • Явный context в публичных API.
  • Пулы воркеров для CPU-bound вместо бесконечного go на каждый байт.
  • Профилирование pprof под нагрузкой.
  • Лимиты на буферы каналов и back-pressure при быстром продюсере.
  • GOMAXPROCS осознанно в контейнерах (CPU quota vs физические ядра).

Дальше: Gin и Fiber · тег Go