Overview
Delve is the Go debugger. Generic debuggers like gdb see OS threads and mangled stacks; Go multiplexes goroutines across threads, grows stacks dynamically, and passes arguments in registers — gdb misreports all of it. Delve understands the runtime's data structures natively: goroutines, channels, interfaces, and maps render as Go sees them.
Key points
- Entry modes:
dlv debug(compile without optimizations and run),dlv test(debug a test binary),dlv attach <pid>(live process),dlv exec(pre-built binary),dlv core <binary> <core>(post-mortem, pairs withGOTRACEBACK=crash). - Goroutine-native:
goroutineslists all of them (with filters/grouping),goroutine <id> btinspects any stack — the view gdb fundamentally lacks. - Conditional breakpoints:
break file.go:42thencondition 1 order.ID == "x"; conditions can target goroutine state (e.g. by goroutine labels viaruntime/pprof.Labels) to stop only the request you care about. - DAP server:
dlv dapspeaks the Debug Adapter Protocol — VS Code, GoLand, and Neovim all drive Delve underneath; there is one debugger, many frontends. - Remote/containers: run
dlv exec --headless --listen=:2345 --accept-multiclient --api-version=2in the container, connect withdlv connector an IDE; map source paths withsubstitute-pathwhen build and dev trees differ. - Build flags matter: debug builds want
-gcflags="all=-N -l"(no optimizations, no inlining) or variables show as optimized away;dlv debugdoes this for you.
Examples
dlv test ./order -- -test.run TestRefund
(dlv) break refund.go:87
(dlv) condition 1 amount > 1000
(dlv) continue
(dlv) goroutines -with user # goroutines currently in user code
Related
- The go command & tool catalog — parent catalog of the toolchain.
- gopls — the editor's other Go backend; gopls for editing, Delve (via DAP) for debugging.
- jdb — the JVM counterpart, similarly wired into IDEs through a shared debug protocol.