TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7089 3.23K
👨‍💻 Семафор в Go через буферизованный канал

Параллелизм в Go легко выходит из-под контроля. Запустил 1000 горутин и сервер задыхается. Семафор ограничивает количество горутин, которые работают одновременно и сервер становится более стабильным.

Что такое семафор и почему в Go его нет

В других языках семафор встроен в стандартную библиотеку. В Go его нет, но есть буферизованный канал и он делает ту же работу.

Логика простая: ёмкость канала = максимальное число параллельных горутин. Хотите запустить горутину — отправьте в канал пустую структуру. Нет свободного места — ждите. Горутина завершилась — прочитайте из канала, освободите слот.

Базовая реализация:
sem := make(chan struct{}, 10) // максимум 10 горутин одновременно

for _, task := range tasks {
sem <- struct{}{} // занять слот (блокирует, если канал полон)
go func(t Task) {
defer func() { <-sem }() // освободить слот при выходе
process(t)
}(task)
}

// Ждём завершения всех горутин
for i := 0; i < cap(sem); i++ {
sem <- struct{}{}
}


У struct{} нулевой размер в памяти. Канал здесь нужен только для сигнализации, а не для передачи данных. Это чисто ибез лишних зависимостей.

Где это ломается

Базовый вариант работает для скриптов и одноразовых утилит. Но у него есть жёсткое ограничение: он не знает про отмену контекста.

Если приложение получило сигнал завершения или истёк дедлайн, горутины, заблокированные на sem <- struct{}{}, просто продолжают ждать. Бесконечно. Приложение не завершится корректно.

Для чего-то серьёзнее скрипта нужен select с ctx.Done().

Версия с отменой контекста:
func acquire(ctx context.Context, sem chan struct{}) error {
select {
case sem <- struct{}{}:
return nil
case <-ctx.Done():
return ctx.Err()
}
}


Теперь при отмене контекста горутина не зависнет, она получит ошибку и завершится.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • 👍 7
  • 🥱 6
  • ❤ 4
More from @goproglib
  1. Sep 30, 2026🧑‍💻 Эмулятор AWS-сервисов Kumo — это небольшой инструмент на Go для локальной имитации A…
  2. Sep 29, 2026👨‍💻 Библиотека для написания LSP-серверов Написать свой Language Server с нуля на Go сло…
  3. Sep 28, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — 1 true / 0 false 🔥 — 1 true /…
  4. Sep 28, 2026👩‍💻 Что на самом деле происходит внутри Go map? После Go 1.24 обычный map внутри работае…
  5. Sep 26, 2026🔥 В Go 1.27 появился portable SIMD До этого SIMD-оптимизации в Go требовали архитектурног…
  6. Sep 25, 2026🤡🤡 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →