Delve: отладчик Go
Delve (dlv) — source-level debugger для Go. Он запускает или присоединяется к процессу, останавливает выполнение в breakpoint и показывает goroutines, stack frames, переменные и выражения. Отладчик отвечает на вопрос о конкретном воспроизведении; для статистических production-проблем чаще подходят метрики, profile и trace.
Зачем это на интервью
Полезно объяснить, как локализовать неверное состояние, не менять код случайными print-логами и не использовать attach к production-процессу как обычный первый шаг.
Минимум для E4
- Установить совместимую версию:
go install github.com/go-delve/delve/cmd/dlv@latest. - Запустить программу
dlv debug ./cmd/api -- -config test.yaml. - Поставить
break main.main, выполнитьcontinue, посмотретьgoroutines,stack,locals,print expr. - Отладить тест
dlv test ./internal/auth -- -test.run '^TestLogin$'.
(dlv) break service.go:42
(dlv) continue
(dlv) locals
(dlv) print req.UserID
(dlv) goroutines
(dlv) goroutine 12
(dlv) stack
(dlv) next
(dlv) step
(dlv) restartУглубление для E5/Senior
Сборка с оптимизациями и inlining может делать переменные «недоступными» или искажать удобство stepping. Для локальной диагностики используют -gcflags=all='-N -l', понимая, что бинарник меняет timing и производительность; итог исправления обязано пройти обычную оптимизированную сборку и тесты. Conditional breakpoint (break file:line if condition) уменьшает шум, а on breakpoint command автоматизирует безопасную печать контекста.
dlv attach PID останавливает/влияет на работающий процесс и часто требует ptrace permissions. В production это исключение: нужны согласование владельца, изолированная реплика, минимальный интервал, контроль доступа и rollback. Remote debugging (dlv --listen=... --headless) никогда не открывают на публичном интерфейсе без защищённого канала; debugger способен читать память и выполнять выражения. Для deadlock исследуют все goroutines и stacks, а не только текущий breakpoint.
Ключевые понятия
| Команда | Назначение |
|---|---|
dlv debug | собрать и начать debug пакета main |
dlv test | запустить тестовый binary под debugger |
break | поставить breakpoint, возможно условный |
next / step | перейти через строку / войти в вызов |
goroutines, stack | исследовать конкурентное состояние |
attach | подключиться к существующему процессу |
Типовые вопросы
nextиstep? —nextпроходит вызов как одну операцию,stepвходит в вызываемую функцию.- Почему debugger не видит переменную? — Её мог оптимизировать или встроить compiler; локально помогает
-N -l, но это не production-поведение. - Как отладить один тест? —
dlv test <package> -- -test.run '^TestName$'передаёт тестовый флаг binary. - Можно ли attach к production? — Технически иногда да, но это остановка/доступ к памяти и operational-risk; сначала применяют менее инвазивные сигналы.
- Как искать deadlock? — Снять stacks всех goroutine, найти ожидаемые locks/channels и сопоставить ownership; не полагаться на одну текущую goroutine.
Практика
- Отладьте failing unit test без изменения production-кода. Готово: есть breakpoint, inspected variable, причина и обычный
go testпосле фикса. - Исследуйте учебный deadlock двух goroutine. Готово: сохранены stacks обоих участников, описан цикл ожидания и исправление проходит
go test -race. - Сравните debug и release сборку. Готово: объяснено влияние
-N -l, а результат подтверждён без этих флагов.
Частые ошибки и ловушки
- Принимать поведение неoptimised debug-binary за доказательство production timing.
- Открывать headless Delve наружу или сохранять memory dumps без политики доступа.
- Использовать
attachпервым средством при инциденте вместо метрик, logs, pprof и trace. - Лечить deadlock
Sleep, не устанавливая порядок владения и отмену.
Связанные темы
Инструменты Go · go test и race detector · pprof · Trace и escape analysis