Go

How do you debug a Go program with Delve (dlv)? How do you attach to a running process, debug a test, and debug goroutines?

Question 564MediumGo 1.22 to 1.25

Delve is the Go debugger. It understands goroutines, the Go scheduler and Go types better than gdb does. The main entry points are:

# build and debug the main package (Delve turns optimizations off for you)
dlv debug ./cmd/api -- -config=dev.yaml

# debug the tests of one package, running only one test
dlv test ./internal/store -- -test.run '^TestUpsert
  

 -test.v

# attach to a running process (Linux may need ptrace_scope=0 or CAP_SYS_PTRACE)
dlv attach 12345

# headless server for an IDE or a remote container
dlv attach 12345 --headless --listen=:2345 --api-version=2 --accept-multiclient

# debug a binary you built yourself: keep variables visible
go build -gcflags=all="-N -l" -o app ./cmd/api && dlv exec ./app

Useful commands: break store.go:42, cond 1 id == 7, continue, next, step, stepout, print x, locals, goroutines (lists every goroutine with its current location), goroutines -group userloc, goroutine 18 followed by bt to switch to a goroutine and see its stack, and threads.

Gotchas: in an optimized binary, variables show as "optimized away" and lines seem to jump around. Rebuild with -N -l. Stopping at a breakpoint pauses the whole process, so timeouts and deadlines in other goroutines may fire when you resume. Attaching to a production pod stops it from serving traffic. Take it out of load balancing first, or capture a goroutine dump (/debug/pprof/goroutine?debug=2) instead.

What the interviewer is looking for: you know the difference between debug, test, attach, exec and core, and you can inspect goroutines to find deadlocks.

More on Observability, Debugging & Production Operations

All 14 Observability, Debugging & Production Operations questions