Writing code is easy, but debugging code is hard. This is especially true in Go, because Go is not as dynamic as Python, like some Web frameworks (e.g. Flask), you can even debug directly in the browser or console when an exception occurs, and you keep the contextual information, which is simply more enjoyable. Of course, we can debug locally in a single step during normal development, but if the program is running in the background or during regular testing, we need some more convenient tools to support it, otherwise we will only have logs to locate the problem.

In Go, in fact, there are not many tools, in addition to some underlying GDB, may be more widely used is left delve, I have also introduced before: using delve remote debug Go applications 7a8adcf0), but it’s relatively simple and less hands-on, so here’s a slight extension to introduce the container and how an already running program can operate.

Use in a container environment

  1. [root@liqiang.io]# cat Dockerfile
  2. FROM golang:1.17
  3. RUN go get github.com/go-delve/delve/cmd/dlv
  4. ADD . /go/src/github.com/liuliqiang/go-demos
  5. WORKDIR /go/src/github.com/liuliqiang/go-demos
  6. RUN make server
  7. # Final stage
  8. FROM busybox:glibc
  9. COPY --from=0 /lib/x86_64-linux-gnu/libdl.so.2 /lib/libdl.so.2
  10. COPY --from=0 /go/bin/dlv /home/liqiang/
  11. COPY --from=0 /go/src/github.com/liuliqiang/go-demos/.build/server /home/liqiang/
  12. EXPOSE 2345 9000
  13. WORKDIR /home/liqiang
  14. CMD ["/home/liqiang/dlv", "--listen=:2345", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", \
  15. "/home/liqiang/server", "--", "-iden", "grpc-server"]

This way, once you have the program running, you have a server that you can debug directly, and then you can debug it remotely via Goland.

Runtime injection

The previous example of container environment is started directly by dlv, which is not universal. A more common scenario is to run a program and then find some exceptions and then open the debugger to inject debugging. is discarded.

  1. [root@liqiang.io]# go build -gcflags="all=-N -l" -o /home/liqiang/server
  2. [root@liqiang.io]# /home/liqiang/server # Run the program
  3. [root@liqiang.io]# ps aux | grep server # Get the pid of the program
  4. root 299664 0.0 0.0 18024 2748 ? Ss 18:41 0:00 bash -c /home/liqiang/server

Inject the program debug.

  1. [root@liqiang.io]# dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient attach 299664

This way the debug server is up and running.

Goland connection for remote debugging

You can configure the Host and Port directly in Goland by selecting the settings in the top right corner of the project.

Figure 1: Config Debug

Then select this “Go Remote” debugger in the source code to debug.

Figure 2: Add Remote Debugger

In the window on the right, enter Host and Port.

Figure 3: Add Debug Server

Parameter Meaning

parameter description default
-accept-multiclient Multiple clients can be accessed at the same time
-api-version The API version to use, this version must match 1