Перейти к содержанию

Delve

Язык: Go · Транспорт: TCP

Запись каталога:

[adapters.dlv]
id = "dlv"
command = "dlv"
args = ["dap", "--check-go-version=false"]
tcp_argument = "--listen={host}:{port}"
transport = { tcp = { host = "127.0.0.1" } }

[adapters.dlv.build]
command = "go"
args = ["build", "-gcflags=all=-N -l", "-o", "{out}", "{program}"]

--check-go-version=false не даёт Delve отказаться от работы, когда версия его сборки расходится с вашим тулчейном Go. Расхождение это обычно безобидное, а иначе оно полностью блокирует отладку.

Установка

go install github.com/go-delve/delve/cmd/dlv@latest
command -v dlv
dlv version

Bugsaur собирает, Delve отлаживает

Это единственный адаптер, у которого в каталоге есть запись build. Bugsaur компилирует программу сам, в фазе building, и отдаёт Delve готовый бинарник по постоянному пути — <корень>/.bugsaur/build/<имя программы>.

Причина измерена, а не выдумана: dlv debug собирает в __debug_bin<случайное> и удаляет за собой, а Go переиспользует слинкованный файл только по тому же пути. Со случайным именем каждый запуск платил полную линковку. На сервисе с бинарником в 74 МБ: 14 с каждый запуск против ~2 с при пересборке без изменений.

Флаги сборки важны

-gcflags=all=-N -l отключает оптимизацию и инлайнинг. Без него в бинарнике не будет ни переменных, ни неинлайненных кадров — ровно того, ради чего вы и запускали отладчик. all= распространяет запрет на зависимости, а не только на main.

Обратите внимание: -gcflags=all=-N -l — это один аргумент с пробелом внутри, и именно поэтому command и args разделены, а не заданы одной строкой.

Перебить сборку

[profiles.worker.build]
command = "go"
args = ["build", "-tags=dev", "-gcflags=all=-N -l", "-o", "{out}", "./cmd/worker"]

{out} — собираемый бинарник, {program} — то, что названо в program.

Когда Bugsaur не собирает

  • mode = "attach" — процесс уже работает;
  • профиль сам назвал Delve mode или program в launch_arguments — значит, запуск ведут руками.

Второе — это как раз отладка тестов пакета: mode = "test" заставляет Delve собрать тестовый бинарник самому, и наша сборка подложила бы ему не тот файл.

Собственные режимы Delve

Два разных ключа mode

mode на уровне профиля — это launch / attach из DAP. mode внутри launch_arguments — собственный режим Delve (debug, test, exec), и он перебивает сгенерированный debug.

[profiles.api.launch_arguments]
mode = "exec"    # отлаживать уже собранный бинарник
[profiles.orders-test.launch_arguments]
mode = "test"    # собрать и отладить тесты пакета

Горутины

Delve сообщает горутины как потоки, поэтому в панели Threads бывают тысячи строк. Так и задумано, и это основной инструмент при разборе взаимной блокировки. См. Потоки.

Диагностика

Симптом Причина Что делать
Сессия не стартует dlv не виден через PATH go install, проверьте command -v
Сессия падает с выводом компилятора не собралось почините код; текст лежит в панели Logs
launch идёт минутами Delve собирает внутри запроса mode = "exec" с заранее собранным бинарником
Точки останова попадают на странные строки оптимизация не отключена оставьте -gcflags=all=-N -l в своей сборке
В тесте не находится testdata/ cwd по умолчанию — корень проекта задайте cwd каталогом пакета