Debugging Go With GoDelveAdd to bookmarks
Wed Jun 03 2020
Finding my way around a terminal-based debugger was an early challenge for me as an engineer, as it probably was for a dozen more engineers. So, here's an article that aims to serve as a soft intro into the CLI debugger for go, delve.
By the end of this tutorial you should be able to: - Run delve in the command line. - Basic debug operations in delve such as: - Navigate the flow of code in the command line. - Debug goroutines.
Delving into code (pun intended :p)
go delve is arguably the most popular and widely used debugger in the go eco-system. This tutorial aims to serve as a soft introduction to delve and how to use it to debug in basic scenarios.
What the code does is simple, we implement a custom ticker in the
timer/timer.go file, the ticker runs a function
n number of times, with an
What the code in the
main.go does is instantiate the CustomTicker with a closure function that prints "Hello World" to
n amount of people,
n being the number of times the closure was run
Running the debugger 🐛
Fire up the debugger with
dlv debug in the project root directory. You can also call it with
dlv debug main.go
The dlv debug session should look like this:
If you type
help into the dlv interface, you'd see a whole (long) list of available commands to aid in your bug hunt, but for now, we will be focusing on the commands for navigating through the code, setting and deleting breakpoint, and manipulating goroutines.
We'll start by adding breakpoints to the code, we will be adding breakpoints to the
main.go at lines 12, 17, 21 so we can see the flow of the program and be able to print some certain variables.
You can view the specifications for the manipulating breakpoint's command below:
You can also view this documentation to view specifications on how to set breakpoints.
So you can go ahead and run this in the dlv interface, and your dlv terminal should look like this:
Now you can continue the program flow by running
continue in the delve session, you should see the program pause at the first breakpoint which is line 12.
From this, you can view the values of your golang variables at runtime. Now we can manipulate values at well at runtime too. E.G changing the
count member of the
runner to 4
Now if you continue the program flow to the next point, your code will either be halted at line 17 or line 21, this depends on how much time was spent running the custom ticker (debug time inccluded). In my case this the output gotten:
From this, I can see that the timeout was triggered before the custom ticker could complete the
You can clear out the breakpoints with:
Now that we've been able to perform basic breakpoint inspection and navigation on our go code, the next thing we want to do in this tutorial is viewing and working with goroutines.
You can change the timeout value in the
main.gofile from 30 seconds to 5 minutes (
5 * time.Minute)
Now the next thing is to start afresh debugging session. Go ahead and run
dlv debug. Now we want to add breakpoints in
timer/timer.go:32 so we can pause the program flow inside two separate goroutines:
At the first breakpoint (
main.go:15) if you run
goroutines in delve you should be able to see all goroutines and the current, which is usually asterisked.
Here are a list of goroutines and from this you can see that at the ccurrent goroutine is the
main.main. If we wanted a stack trace (which should be near empty) of this goroutines, you can run the command:
Now, continue the command with
c and the program should pause at the next breakpoint which should be
Now we know how to view the current goroutines and the stack traces. For this second breakpoint we can view the stacktracce of the .Begine() goroutine. i.e:
That's it for now in this light intro to go debugging. In a later tutorial, we will be covering more advanced concepts including profiling and monitoring go code.