Victor Jonah I am a Software Developer with over three years of experience working with JavaScript and its frameworks. I currently work as a remote software developer for a tech agency.

Comparing Go debugging tools

7 min read 2066

Comparing Go Debugging Tools

If you build software applications in Go, you know code doesn’t always work as expected.

This problem can then continue to compound with swearing at your computer, compiling the code over and over to see whether it will work by chance, and endlessly searching through large chunks of code to see where the error comes from.

But, you can save yourself the headache by choosing one of the many Go debugging tools. Debugging itself is just finding bugs in code, but debugging without any tools is all sweat and tears.

In this article, we will compare a few of the most popular Go debugging tools by looking at their installations, debugging processes, and pros and cons, including:

But before we move into that, it is best to discuss what debugging tools are, why we as developers need them, and the issues Go developers face that these tools can help solve.

The only prerequisite for this article is to be familiar with the Go programming language.

What are debugging tools?

Debugging is the process of detecting, finding, and solving defects or problems in a software application. It’s like being the detective in a crime movie while simultaneously being the murderer.

Debugging tools help you closely spot these errors while executing the code so you can remove or fix them, helping you go step-by-step or line-by-line of your code to find them. These errors often include syntax, semantic, and run-time errors.

Using a debugging tool and pausing the execution while you follow the line of code as it executes is one reason why developers have opted to use them. It is the only way you can fully and quickly grasp what is going on in your codebase.

Using this tool, you can immediately see what happens. It is also a great learning method because you actually see how the computer interprets the code.

Debugging techniques

Let’s look more at some common debugging techniques in Go to quickly check for errors in your code.



Using print

This is a practice of adding extra print statements to your code so you can see what logs to your console. With this, you can see the values of variables, how expressions execute, and check whether you’re reaching variable scopes or not.

There is a lot to see but this depends on what you need logged to your console.

However, this is a good trick if you do not use any debugging tools. One advantage of using print is that you can see the flow of your variables and statements on the go.

But, if you build a large-scale application with a lot of functionalities, there is no better surrogate than having a logging system in your codebase.

Also, using print can be messy, convoluting the readability of your codebase with print typed everywhere. They can become too much if you forget to remove them as you find the errors and you cannot turn print off.

Using a debugger

Most IDEs have a built-in debugger that can help detect errors in your code. It is another quick way to debug your code after using print. Debuggers are only found in IDEs, like Visual Studio Code or Eclipse.

Using a debugger helps discover breakpoints, moving line-by-line in your code watching variables flow. With these, you can find logical errors quickly.

Most developers call this technique the step-by-step execution because it moves from line to line and is a quick way to detect bugs.

But while using a debugger is still one of the most preferred techniques for debugging, using the debugger can be tedious in very large applications, which is why I personally prefer using logs, that is, writing log messages to standard output.

Using error detection tools

These tools can help find any breach of errors based on their type. This means there are certain types of error classes these tools can find, such as memory leaks by detecting memory errors.

These tools are also regarded as error monitoring tools because they mainly give the ability to visualize the error to understand what happened and where it happened.

Other common techniques for debugging include backtracking and divide-and-conquer.

Go Debugging tips

Before we get into the different types of Go debugging tools, let’s discuss a few notes to keep in mind while debugging a Go application.

Understand your debugger

If you want to use a debugger like Delve, ensure you understand how it works; learn its commands, how to set breakpoints, and other basics for using the debugger. With this in my mind, you can approach bugs with those tools effectively.

Think about debugging while coding

You should also have a logging system to quickly log information as you code. But, don’t forget to avoid logging sensitive information, like passwords or financial information.

Watch out for simple bugs

Avoid thinking about the worst scenario; your bug might be simple, such as having a wrong spelling somewhere or using the wrong variable name. It’s always the least expected thing.

Go debugging tools

With our understanding of debugging and debugging methods, let’s review some Go debugging tools that can be helpful when working in Go. These tools should give you better insight as to why development is a lot easier when you use them.

Delve

The first and most common debugger for Go is Delve. The goal of using Delve is to provide a simple and full-featured tool for debugging in Go.

One cool thing about Delve is that it was built from the ground up as a debugger for Go, so the actual target for this tool is the Go programming language, unlike other debuggers in IDEs that can be used for various languages.

This is extremely helpful because it knows how to tackle Go-specific features and functionalities like Goroutines, syntax expressions, data structures, and runtime.

To get Delve, you must install it on your computer.

Installing Delve

Delve supports all platforms, including Linux, Windows, and macOS.

Installation is the same for macOS, Windows, and Linux, and all you need to do is use the go install command:

$ go install github.com/go-delve/delve/cmd/[email protected]

After this finishes installing, you can run go help to check where the dlv saved.

If on macOS, you must also install the developer tools to use Delve:

$ xcode-select --install

Below are a few of Delve’s commands to use while debugging:

       --accept-multiclient               Allows a headless server to accept multiple client connections.
      --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
      --backend string                   Backend selection (see 'dlv help backend'). (default "default")
      --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
      --check-go-version                 Checks that the version of Go in use is compatible with Delve. (default true)
      --disable-aslr                     Disables address space randomization
      --headless                         Run debug server only, in headless mode.
  -h, --help                             help for dlv
      --init string                      Init file, executed by the terminal client.
  -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
      --log                              Enable debugging server logging.
      --log-dest string                  Writes logs to the specified file or file descriptor (see 'dlv help log').
      --log-output string                Comma separated list of components that should produce debug output (see 'dlv help log')
      --only-same-user                   Only connections from the same user that started this instance of Delve are allowed to connect. (default true)
  -r, --redirect stringArray             Specifies redirect rules for target process (see 'dlv help redirect')
      --wd string                        Working directory for running the program.

Debugging with Delve

To start a debugging session in Delve, run the command below to compile your program:

$ dlv debug

The dlv debug compiles and runs the main package in the current directory for debugging. You can also specify the package after the command, such as using dlv debug ./hello:

# run delve
$ dlv debug ./hello
Type 'help' for list of commands
(dlv)

To know more about using Delve, you can always use the help command.

Delve drawbacks

Delve has become more stable and mature over the years because it is was quite uncomfortable to use at its inception. The only drawback of using Go Delve is that it does not have a simple tutorial for using the commands.

To get started, you can refer to their Github for more information.

GDB

GBD is another Go debugger owned by The GNU Project. Unlike Delve, it was not built for Go.

Its current version available for download is 11.1, which was released in September 2020.

With GDB, you can inspect your compiled Go package as long as you give it the correct debugging information. And, you do not need to touch your source code to debug because GBD inspects what is happening inside your program while it executes.

GDB can do a few things while debugging your code to find bugs, including:

  • Beginning your program and specifying what is affecting its behavior
  • Stopping your program on specific breakpoints
  • Scrutinizing the result of your code
  • Allowing changes to your code so you see what is correct in the program

Installing GDB

GDB works for all platforms, including macOS, Windows, and Linux, but they also target UNIX-like systems.

Installing GBD on macOS is pretty easy and straightforward:

brew install gdb

Installing on Windows, however, requires you to download the installer from minGW. This installs GDB for you using the manager. If you use a Linux system, you already have GDB installed.

To begin a debugging process with GBD, you must compile your program. Let’s say your code is in the hello.go file:

go build -gcflags "-N -l" hello.go

Since GDB does not support Go fully, if after compilation the Go compiler performs optimization, it is difficult for GDB to debug properly. So, using -N -l prevents Go from performing its default optimization.

Next, use the gdb command to begin:

gdb hello

Then, use the command run to run your program in GDB:

(gdb) run

When it runs, you can set a breakpoint to stop the program from running at that line:

 (gdb) b 5

Our breakpoint is at the line of the hello.go file. Other basic commands include print, execute, continue, and a few others. For more debugging tips with GDB you can refer to the documentation.

GDB drawbacks

If you notice, a drawback from using GDB when debugging in Go is that it does not fully support and understand the Go language like Delve does. This means you must prevent Go from optimizing your source code so GDB can perform properly.

Also, it is a little difficult to install GDB on Windows, unlike Delve where you can install it simply using the CLI. A few have even complained that the Eclipse IDE does not fully work well with GDB.

Println

PrintIn is a default tool for debugging in Go. It is a function that prints to the console and is a variadic function, meaning it’s a function that can take an unknown number of arguments.

It provides a simple practice of adding print statements to your code so you can see what is happening to the variables and the expressions.

Using Println does not require installation like the others since it’s a default Go tool:

 package main

// Importing fmt
import (
    "fmt"
)

func main() {

    const name = "Victor"

    fmt.Println("Hello", name)
}

Using this can be very useful and save you time where you just print variables to the console to see the outcome. It is another great way to troubleshoot your code, find potential problems, and is a good logging tool overall.

PrintIn drawbacks

While this method of debugging can be easier, it can also be very overwhelming, from inspecting a hundred lines of code and clustering with Println.

A better alternative is to use a logging framework that sends all the debugging messages to a log file.

Conclusion

We looked at a few techniques to debug your code with some popular debugging tools. Having the right tool can be a challenge, and there are many for Go.

Delve is the only debugging tool created specifically for Go, which makes it an obvious first choice.

Unfortunately, for some tools like Godebug that have suddenly been depreciated, we still hope more will be available for the Go community in the future.

Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    LogRocket.init('app/id');
    Add to your HTML:

    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
Victor Jonah I am a Software Developer with over three years of experience working with JavaScript and its frameworks. I currently work as a remote software developer for a tech agency.

Leave a Reply