> Как отследить и исправить deadlock в Go при работе с каналами и горутинами (Go)
Уровень: senior · Роль: backend · Категория: Технические вопросы
Компании: Wildberries
Стек: Go
> Пример ответа
Для отслеживания deadlock'ов в Go используйте встроенный детектор гонок (-race) и профилирование через pprof. Deadlock с каналами часто возникает, когда горутина ждёт данные из канала, который никогда не получит записи, или все горутины блокируются на взаимном ожидании.
Отслеживание:
-
Запустите приложение с флагом
-race:go run -race main.go. Детектор сообщит о проблемах синхронизации, но не всегда явно укажет на deadlock. -
Используйте
net/http/pprofдля снятия дампа горутин: добавьтеimport _ "net/http/pprof"и запустите HTTP-сервер. Затем выполнитеcurl http://localhost:6060/debug/pprof/goroutine?debug=2- вы увидите стек вызовов всех горутин. Если несколько горутин застряли на операциях с каналами (например,chan sendилиchan receive) без прогресса, это deadlock.
Исправление:
- Используйте
selectс таймаутом илиdefault, чтобы избежать бесконечного ожидания:
GOselect {case msg := <-ch:// обработкаcase <-time.After(1 * time.Second):// таймаут}
-
Для однонаправленных каналов убедитесь, что отправитель и получатель работают согласованно. Например, если горутина пишет в канал, а другая читает - проверьте, что обе запущены и не завершились преждевременно.
-
Используйте контекст (
context.Context) с отменой для graceful shutdown:
GOctx, cancel := context.WithCancel(context.Background())go worker(ctx, ch)// при завершенииcancel()
- Избегайте циклических зависимостей: если горутина A ждёт данные от B, а B от A - это deadlock. Разорвите цикл, добавив буферизированный канал или перепроектировав логику.
Пример исправления: замените небуферизированный канал на буферизированный (размер 1), если одна горутина отправляет, а другая ещё не готова принять. Но лучше использовать select для неблокирующих операций.
> Похожие задачи по backend
Как пришли в Go
Куда помещать горутину для чтения из канала в Go
Как архитектурно передавать на фронт сложную структуру с вложенными полями и массивами
В какой версии Go был исправлен баг с указателями в цикле
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью