A partir do Go 1.27, podemos finalmente detectar goroutine leaks de forma nativa e sem precisar de flags experimentais. Neste post, vamos entender como funciona esse novo perfil de detecção e como usá-lo na prática para evitar um dos bugs mais difíceis de rastrear em aplicações Go.
O que é um Goroutine Leak?
Um goroutine leak ocorre quando uma goroutine fica bloqueada indefinidamente em alguma primitiva de concorrência (channels, sync.Mutex, sync.Cond, etc.) e nunca consegue ser desbloqueada. Diferente de uma goroutine que apenas dorme, uma goroutine em leak está prisioneira — nenhum outro código pode libertá-la.
Isso é um problema sério porque goroutines consomem memória. Se sua aplicação cria milhares delas sem desbloqueá-las, você terá vazamento de memória gradual e difícil de diagnosticar.
Como o Runtime Detecta Leaks
O Go 1.27 usa uma abordagem elegante baseada no garbage collector:
- O runtime executa um ciclo de GC (Garbage Collector)
- Para cada goroutine, verifica se ela está bloqueada em uma primitiva de concorrência
- Verifica se aquela primitiva é alcançável a partir de alguma goroutine que possa ser desbloqueada
- Se a primitiva for inalcançável, a goroutine está vazando
Esse mecanismo funciona porque se uma primitiva é inalcançável, ninguém pode sinalizar para ela, portanto a goroutine nunca acordará.
Usando o Perfil goroutineleak
No Go 1.27, você não precisa mais da flag GOEXPERIMENT=goleakleak. O perfil goroutineleak está disponível nativamente no pacote runtime/pprof.
Acessando o Perfil via Código
package main
import (
"os"
"runtime/pprof"
)
func main() {
// ... seu código ...
// Salvar o perfil em um arquivo
f, err := os.Create("goroutineleak.prof")
if err != nil {
panic(err)
}
defer f.Close()
err = pprof.Lookup("goroutineleak").WriteTo(f, 0)
if err != nil {
panic(err)
}
}
Via HTTP Endpoint
Se sua aplicação expõe o pacote net/http/pprof, o endpoint /debug/pprof/goroutineleak fica automaticamente disponível:
curl http://localhost:6060/debug/pprof/goroutineleak > goroutineleak.prof go tool pprof goroutineleak.prof
Exemplo Prático: Detectando um Leak
Considere este código que cria um leak:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int) // canal sem buffer
// Esta goroutine fica bloqueada esperando receber do canal
go func() {
fmt.Println(<-ch)
}()
// Simula o resto da aplicação
time.Sleep(2 * time.Second)
// A goroutine nunca receberá nada — leak!
}
Rodando com o novo perfil:
# Compilar go build -o myapp . # Executar ./myapp & # Capturar o perfil curl http://localhost:6060/debug/pprof/goroutineleak > leak.prof # Analisar go tool pprof leak.prof # Você verá a goroutine bloqueada no canal, com a stack trace completa
Quando Usar na Prática
O perfil goroutineleak é particularmente útil em:
- Testes automatizados: Adicione verificações antes e depois de testes para garantir que nenhuma goroutine vazou
- Debugging em produção: Capture perfis periodicamente para monitorar leaks
- Code reviews: Verifique se handlers HTTP e workers limpam suas goroutines corretamente
Conclusão
O Go 1.27 traz uma ferramenta nativa e eficiente para detectar goroutine leaks — um dos bugs mais insidiosos em aplicações concorrentes. Agora você pode identificar e corrigir esses problemas com precisão, sem depender de flags experimentais ou ferramentas externas.
Se você trabalha com Go e concorrência, é recomendável integrar essa verificação em seus testes e monitoramento.
Gostou do conteúdo?
- ✅ Inscreva-se na newsletter para receber mais dicas práticas sobre Go diretamente no seu e-mail!
- 🚀 Conheça a Imersão Golang e leve seus conhecimentos em Go para o próximo nível!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.