Debugging Go With GoDelve

Add to bookmarks

Wed Jun 03 2020

Introduction

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.

Goal

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.

Begin by installing delve to your machine. Next, you need to clone the project we will be using for this tutorial.

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 interval

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.

Setting breakpoints

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 .Begin() call.

You can clear out the breakpoints with:

Viewing Goroutines

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.go file 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 main.go:15 and 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 continue && c and the program should pause at the next breakpoint which should be timer/timer.go:32

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:

Conclusion

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.