My employment depends on me writing a lot of Go, seems like a good idea to become familiar with the tools that make writing Go easier. A few weeks back I spent an afternoon learning how to be more effective with the debugger. Being more comfortable with has already been useful in tracking down a couple tricky bugs. Here are a few notes on using .
You can stop reading here if youβd like. The next few bullets are just a TLDR from the video. The TLDR of the TLDR is that
helpwill do you a lot of good.
Watch this video with one of the developers twice through, it will get you productive in .
Start an interactive debugging session with
dlv debug main.go.
break ${file}:${lineNumber} or
break ${ns}.${function} to set breakpoints.cond ${breakpointNumber} ${condition} to break only if
${cond} is truetoggle ${breakpointNumber} to enable/disable
breakpointsc to continue to the next breakpoints to step into the next line (up
and down to move up and down the stack)n to step over the next linevars to get all variables and their namespace,
args to get local contextp ${code} to execute code as if weβre in an interactive
shellr to rebuild and restart the
programwatch -w ${object} set break on all writes to
$objectTrace with dlv trace main.go ${regexp} β Iβm sure
thereβs some value here. Could be nice to set the regexp to
${module} and trace the execution of your moduleβs
code. A little lighter touch than using the interactive
debugger.
Delve has a server that you can attach to by exposing additional ports in your container image. Not ideal IMO. One can pass the following arguments to to do this. Iβm told the following integrates better with IDEs, etc.
CMD ["/dlv", "--listen=:40000", "--backend=default", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "/bin/main" ]
Debugging in a container can be made very easy. Most expedient way is just adding to your Dockerfile and then attaching to the running process. There is some downside here. By default produces an unoptimized binary (e.g.Β ) to prevent the compiler from making choices that can make debugging harder. Small price to pay, proceed with cautionβ¦
git diff default.Dockerfile debug.Dockerfile
diff --git a/default.Dockerfile b/debug.Dockerfile
index b836d46..7032666 100644
--- a/default.Dockerfile
+++ b/debug.Dockerfile
@@ -4,9 +4,11 @@ FROM golang:1.21-alpine AS builder
WORKDIR ./
COPY ./main.go ./main.go
RUN go build -o /bin/main ./main.go
+RUN go install github.com/go-delve/delve/cmd/dlv@latest
# stage 2: final img
FROM alpine
COPY --from=builder /bin/main /bin/main
+COPY --from=builder /go/bin/dlv /
EXPOSE 4221 ## for the application, not for the debugger...
CMD ["/bin/main"]Iβd need to read up a bit more on system capabilities. One can run docker with
--sysctl ${cap}, but granting container code admin access to the host seems like a disaster in the makingβ¦
--backend=rr and then the session is
recorded. Getting this to work safely, correctly, and in a container on
M1 seems challenging. Weβll seeβ¦