Отладка Go в Bugsaur¶
Адаптер: dlv (Delve)
Поставить адаптер¶
Настроить¶
bugsaur init опознаёт проект по go.mod и пишет по профилю на каждый каталог
с package main: сам корень модуля и прямые подкаталоги cmd/.
Один бинарник в корне¶
Рабочий каталог — корень, .env читается. То же самое, что go run . из корня.
Несколько команд в cmd/¶
go-order/
├── go.mod
├── .env
├── configs/dev.yaml
├── migrations/
└── cmd/
├── go-order/main.go package main
├── worker/main.go package main
└── shared/shared.go package shared ← не команда, профиля нет
version = 1
default = "go-order"
[profiles.go-order]
adapter = "dlv"
program = "cmd/go-order"
[profiles.worker]
adapter = "dlv"
program = "cmd/worker"
Рабочий каталог у обоих профилей один — корень модуля, — поэтому .env,
configs/ и migrations/ видны каждой команде и cwd писать не нужно.
Переключение: :DebugStart worker.
Go собирает сам Bugsaur¶
В отличие от остальных языков, Go-бинарники собирает Bugsaur — до старта
адаптера, в фазе building, — и адаптеру отдаёт уже готовый файл. Настраивать
это не нужно, оно включено по умолчанию.
Зачем. dlv debug собирает внутри запроса launch, кладёт результат в
__debug_bin<случайное> и удаляет его за собой. Go не кэширует слинкованный
исполняемый файл — он переиспользует его только по тому же пути. Из-за
случайного имени каждый запуск платил полную линковку. Замерено на сервисе с
бинарником в 74 МБ:
dlv debug |
своя сборка | |
|---|---|---|
| первый запуск | 14 с | 25 с |
| повторный, код не менялся | 14 с каждый раз | ~2 с |
Куда. <корень>/.bugsaur/build/<имя программы> — путь постоянный, на этом
всё и держится. Ключ — программа, а не профиль, поэтому два профиля одного
бинарника переиспользуют одну сборку. Каталог игнорирует себя сам, дописывать
.gitignore не нужно.
Чем. По умолчанию — тем, что каталог адаптеров знает про dlv:
go build -gcflags=all=-N -l -o {out} {program}. Профиль может перебить:
[profiles.worker]
adapter = "dlv"
program = "cmd/worker"
[profiles.worker.build]
command = "go"
args = ["build", "-tags=dev", "-gcflags=all=-N -l", "-o", "{out}", "./cmd/worker"]
command и args по отдельности, а не одной строкой: в -gcflags=all=-N -l
пробел находится внутри одного аргумента, и разбор строки потребовал бы правил
кавычек ровно там, где ошибка тихо ломает отладочную информацию. Подстановки:
{out} — собираемый бинарник, {program} — то, что названо в program.
Когда не собирается: в режиме attach; для адаптеров, сборки которых нет в
каталоге; и когда профиль сам назвал адаптеру mode или program в
launch_arguments — значит, запуск ведут руками.
Если сборка не удалась, сессия падает в failed с текстом компилятора, а
адаптер не поднимается вовсе.
Отладить тест¶
[profiles.orders-test]
adapter = "dlv"
program = "internal/orders"
# `go test` запускает бинарник из каталога пакета — без этой строки
# `testdata/` не найдётся, потому что по умолчанию cwd — корень.
cwd = "internal/orders"
[profiles.orders-test.launch_arguments]
mode = "test"
Либо пользуйтесь отладкой теста под курсором, для которой профиль не нужен:
См. Рецепты → Отладка тестов Go.
Долгая сборка: отдать Delve готовый бинарник¶
Если сборка долгая всегда, честнее вынести её из сессии:
Тогда launch отвечает мгновенно. Цена — пересборка руками после каждой правки.
Два разных ключа mode
mode на уровне профиля — это launch / attach. mode внутри
launch_arguments — режим самого Delve (debug, test, exec), и он
перебивает сгенерированный debug.
Монорепа и go.work¶
Корнем становится ближайший модуль. Общий .env выше него — это одна строка:
# services/api/.bugsaur/config.toml
[profiles.api]
adapter = "dlv"
program = "."
env_file = "../../.env"
Маркером служит go.mod; про go.work определение не знает.
Диагностика¶
| Симптом | Вероятная причина | Куда смотреть |
|---|---|---|
| Сессия падает с выводом компилятора | не собралось | почините код; текст лежит в панели Logs |
launch висит минутами |
Delve собирает внутри запроса | используйте mode = "exec" выше |
| В списке тысячи потоков | это горутины | Потоки |
В тесте не находится testdata/ |
cwd по умолчанию — корень |
задайте cwd каталогом пакета |
| Сессия не стартует | dlv не виден через PATH |
Адаптер не запускается |