Delve¶
Language: Go · Transport: TCP
The catalog entry:
[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 keeps Delve from refusing to run when its build and
your Go toolchain differ in version — a mismatch that is usually harmless and
otherwise blocks debugging entirely.
Install¶
Bugsaur builds, Delve debugs¶
This is the one adapter for which the catalog carries a build entry. Bugsaur
compiles the program itself, in a building phase, and hands Delve a finished
binary at a stable path — <root>/.bugsaur/build/<program name>.
The reason is measured, not theoretical: dlv debug builds into
__debug_bin<random> and deletes it afterwards, and Go only reuses a linked
executable at the same path. With a random name, every run paid for a full link.
On a service with a 74 MB binary: 14 s every run, versus ~2 s for an unchanged
rebuild.
The build flags matter¶
-gcflags=all=-N -l disables optimisation and inlining. Without it the binary
has neither variables nor un-inlined frames — precisely what you started the
debugger for. all= extends the rule to dependencies, not just main.
Note that -gcflags=all=-N -l is one argument containing a space, which is
why command and args are separate lists rather than a single string.
Overriding the build¶
[profiles.worker.build]
command = "go"
args = ["build", "-tags=dev", "-gcflags=all=-N -l", "-o", "{out}", "./cmd/worker"]
{out} is the binary being built; {program} is what program names.
When Bugsaur does not build¶
mode = "attach"— the process is already running;- the profile names
modeorprogramto Delve itself inlaunch_arguments— you are driving the launch by hand.
The second is how package-test debugging works: mode = "test" makes Delve build
the test binary itself, and our build would hand it the wrong file.
Delve's own modes¶
Two different mode keys
mode at the profile level is DAP's launch / attach.
mode inside launch_arguments is Delve's own — debug, test, exec —
and it overrides the generated debug.
Goroutines¶
Delve reports goroutines as threads, so the Threads panel can list thousands of rows. That is the intended behaviour and the main tool for investigating a deadlock. See Threads.
Diagnostics¶
| Symptom | Cause | Fix |
|---|---|---|
| Session never starts | dlv not on PATH |
go install, check command -v |
| Session fails with compiler output | the build failed | fix the code; the text is in the Logs panel |
launch takes minutes |
Delve is building inside the request | mode = "exec" with a pre-built binary |
| Breakpoints land on odd lines | optimisation was not disabled | keep -gcflags=all=-N -l in a custom build |
testdata/ not found in a test |
cwd defaults to the project root |
set cwd to the package directory |