Утечки горутин в Go 1.24+

Вы конечно и так в курсе, но на всякий случай:

Утечка происходит, если одна или несколько горутин навсегда заблокировались на канале (или другом примитиве синхронизации), но другие горутины и программа в целом при этом продолжают работать.

Утрированный пример утечки:

func work() chan int {
    ch := make(chan int)
    go func() {
        ch <- 42
        ch <- 13 // (!) утечка
    }()
    return ch
}

func main() {
    <-work()
    // ...
}

Традиционно Go не очень-то помогал в поиске утечек. Обнаружить их можно было разве что пристально разглядывая профиль или трассировку с продакшена, а в тестах приходилось использовать сторонний пакет goleak от Убера.

Сейчас это меняется.

Сначала в Go 1.24 добавили пакет synctest, который прекрасно справляется с поиском утечек при тестировании. Об этом почему-то никто не говорит — наверно, потому что не проходили мой курс по многозадачности 😁

func Test(t *testing.T) {
    synctest.Test(t, func(t *testing.T) {
        <-work()
        synctest.Wait()
    })
}
panic: main bubble goroutine has exited but blocked goroutines remain

goroutine 37 [chan send (durable), synctest bubble 1]:
main.work.func1()
    leak_test.go:12 +0x3c
created by main.work in goroutine 36
    leak_test.go:10 +0x6c

Как видите, тест и ругнулся, и точно указал, где возникла утечка.

А теперь в Go 1.26 подвезут новый pprof-профиль под названием goroutineleak — он надежно (без ложных срабатываний) обнаруживает утечки в продакшене (как вы понимаете, synctest-то в продакшене не запустишь).

func main() {
    prof := pprof.Lookup("goroutineleak")

    defer func() {
        time.Sleep(50 * time.Millisecond)
        prof.WriteTo(os.Stdout, 2)
    }()

    <-work()
}
goroutine 3 [chan send (leaked)]:
main.work.func1()
    leak.go:12 +0x3c
created by main.work in goroutine 1
    leak.go:10 +0x74

Как видите, указал ровно на ту же утечку, что synctest.

В общем, рекомендую оба инструмента. За подробностями велкам в статью:

Detecting goroutine leaks in modern Go

★ Подписывайтесь на канал и проходите курсы.