TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7441 3.69K
💡 5 приёмов поиска утечек горутин в Go

Утечки горутин — скрытая проблема, которая со временем приводит к росту потребления памяти, деградации производительности и неожиданным падениям. В отличие от «обычных» багов, такие ошибки долго не проявляют себя, а в продакшене отлавливать их уже поздно.

Ниже 5 рабочих приёмов, которые помогут держать горутины под контролем.

1. Мониторинг количества горутин

Запуск фоновой задачи, которая периодически считывает runtime.NumGoroutine() и сравнивает с базовым уровнем — если количество горутин выросло выше порога, сигнализировать (лог, алерт).


go func() {
for range ticker.C {
n := runtime.NumGoroutine()
if n > base+50 { // ваш порог
log.Printf("горутин многовато: %d (base %d)", n, base)
}
}
}()


2. Трассировка с помощью go tool trace

При сложных сценариях запускают трассировку жизненного цикла горутин: когда они создаются, когда завершаются, как взаимодействуют.


func main() {
f, _ := os.Create("trace.out")
defer f.Close()
_ = trace.Start(f)
defer trace.Stop()

for i := 0; i < 10; i++ {
go func() { time.Sleep(500 * time.Millisecond) }()
}
time.Sleep(2 * time.Second)
}



go run . # создаст trace.out
go tool trace trace.out


3. Контекстная отмена

Важно проксировать контекст через цепочку вызовов (например, в HTTP-хендлерах). Когда клиент прерывается или таймаут срабатывает — все дочерние горутины получают сигнал отмены и должны корректно завершаться.


func worker(ctx context.Context, jobs <-chan int) {
for {
select {
case <-ctx.Done():
log.Println("worker: cancelled")
return
case j, ok := <-jobs:
if !ok {
return
}
_ = j // делаем работу
}
}
}



func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

jobs := make(chan int)
go worker(ctx, jobs)

go func() { // имитация продьюсера
for i := 0; i < 100; i++ {
select {
case <-ctx.Done():
close(jobs)
return
case jobs <- i:
}
}
}()

time.Sleep(3 * time.Second)
}


4. Интеграция goleak в тесты

В тестовой среде использовать goleak.VerifyTestMain или goleak.VerifyNone (внутри тестов) для автоматического обнаружения оставшихся горутин. Это помогает не допустить утечки до продакшена.


func TestMain(m *testing.M) { // глобальная проверка
goleak.VerifyTestMain(m)
}

func TestNoLeaks(t *testing.T) {
defer goleak.VerifyNone(t)

// Демонстрация «правильной» горутины
done := make(chan struct{})
go func() {
time.Sleep(10 * time.Millisecond)
close(done)
}()
<-done
}


5. Graceful shutdown

При завершении сервера или приложения — ждать, пока работающие операции завершатся, использовать таймауты, отслеживать завершение горутин.

Эти паттерны не заменяют внимательного дизайна кода, но дают страховку

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

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

#GoDeep
  • 👍 10
  • ⚡ 2
  • 🤔 2
  • 😁 1
  • 👾 1
More from @goproglib
  1. Sep 23, 2026💥 TCP/IP: что происходит с данными в сети Когда Go-приложение отправляет данные по сети,…
  2. Sep 22, 2026🔴 Встроенные функции len, make, panic — встроенные функции Go, которые можно использовать…
  3. Sep 21, 2026🤩 Go с нуля: серия базовых шпаргалок Собрали путь от Hello, World! до goroutines, channel…
  4. Sep 20, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — [1 2 3 4 5] / [1 2 10] 🔥 — [1…
  5. Sep 19, 2026🛠 Rune — open-source IDE и terminal multiplexer на Go Rune объединяет IDE, терминал и AI-…
  6. Sep 18, 2026🤩 SQLite вместо отдельного брокера в Go Watermill поддерживает SQLite Pub/Sub — сообщения…
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 →