Featured resource
pluralsight tech forecast
2025 Tech Forecast

Which technologies will dominate in 2025? And what skills do you need to keep up?

Check it out
Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Debugging Go with the Delve CLI

This Code Lab will teach you how to debug Go applications using the Delve CLI debugger. You'll learn essential debugging techniques such as setting breakpoints, inspecting variables, and controlling program execution to identify and fix bugs in a simple Go program.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 26m
Published
Clock icon Oct 24, 2024

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    Welcome to the Guided: Debugging Go with the Delve CLI Code Lab!

    In this lab, you'll learn how to debug Go applications using the Delve command-line debugger.

    You'll be working with a simple Go application in the main.go file. This program calculates the average of a list of integers and prints the result to the console. However, there's a bug that's preventing it from running correctly.

    To see the error, you can run the program by either clicking the Run button in the bottom-right corner of the Terminal tab or by executing the following command:

    go run main.go
    

    In the upcoming steps, you'll:

    • Start a Delve debugging session
    • Learn how to set breakpoints
    • Step through the code to identify and fix the bug

    Throughout the lab, all commands entered in the Delve CLI will be logged to a file to track your progress. You'll use a script that wraps around the actual dlv (Delve) command, called ./dlv. This wrapper ignores the Delete and arrow keys; however, you can use the Backspace key to correct mistakes. The log file is overwritten every time you start a new debugging session.

    Now, move on to the next step to dive deeper into the Delve debugger and its most important commands.

  2. Challenge

    Exploring Delve Basics

    Delve is a powerful debugger built specifically for Go programs, enabling developers to inspect and control the execution of their code.

    To start debugging a Go application with Delve, use the debug subcommand:

    dlv debug <package>
    
    • <package>: The package or file to debug. If omitted, Delve will debug the package in the current directory.

    This command compiles the program with debugging information and opens an interactive debugging session.

    Once you're in a Delve session (indicated by the (dlv) prompt), you can use a variety of commands to control execution and inspect the program state. Here are some fundamental commands:

    • help: Lists all available commands and their descriptions
    • break or b: Sets a breakpoint at a specific function or line
    • continue or c: Runs the program until it hits the next breakpoint or reaches the end
    • next or n: Moves execution to the next line in the current function
    • step or s: Steps into functions to debug them line by line
    • stepout or so: Continues execution until the current function returns
    • print or p: Evaluates and displays the value of variables or expressions
    • args: Lists the current function's arguments
    • locals: Displays local variables in the current scope
    • list or l: Displays the source code
    • exit, quit, or q: Exits the debugging session

    Setting Breakpoints

    Breakpoints allow you to pause program execution at specific points and inspect the program state. For example, you can set breakpoints by function name:

    break <function_name>
    

    Or by file and line number:

    break <file_name>:<line_number>
    

    Navigating Through Code

    Controlling the flow of execution is key to understanding how your program works:

    • continue: Resumes execution until the next breakpoint or the end of the program
    • next: Moves to the next line in the current function, stepping over any function calls
    • step: Steps into the next line of code, including called functions
    • stepout: Runs the program until the current function returns

    Inspecting Program State

    When the program is paused, you can inspect variables and the call stack using these commands:

    • print <expression>: Evaluates and displays the value of an expression or variable
    • args: Lists the current function's arguments and their values
    • locals: Shows local variables and their values in the current scope
    • list: Displays your current location and the surrounding source code
    • stack: Displays the current call stack, useful for understanding the sequence of function calls

    Exiting and Restarting the Debugger

    When you're done debugging or want to restart the program, you can use the following commands:

    • restart: Restarts the program from the beginning while keeping breakpoints intact
    • exit, quit, or q: Exits the Delve debugger and returns you to the shell

    In the next tasks, you'll use these commands to navigate the code, set breakpoints, and inspect variables. Familiarizing yourself with help and all the available commands will aid in navigating and controlling the debugging session.

    Tips:

    • You can type help and the name of a command to know more about it.
    • Abbreviated commands can speed up your workflow inside Delve. Remember, setting breakpoints allows you to pause execution at specific points and inspect the program's state.

    Tips:

    • You can set breakpoints using function names or line numbers.
    • Remember that the order of commands matters when debugging. Navigating through your code and inspecting variables is essential for effective debugging.

    Tips:

    • Remember, you can move to the next line in the current function, stepping over any function calls.
    • Or, you can step into function calls and examine them line by line. Understanding the function's inputs and variables is important when debugging.

    Tips:

    • Commands that list function arguments or local variables may not display the values directly. To view the value of a specific variable, use the appropriate command to print it.
    • If you're unsure where you are in the source code, use the command that shows your current location and surrounding lines.
    • Familiarize yourself with how to inspect variables and navigate the code to effectively diagnose issues. Understanding how functions are called and how they return is important for debugging complex programs.

    Tips:

    • Use the command that allows you to exit the current function and return to the caller, effectively moving up one level in the call stack.
    • To inspect the call stack, use the command that displays all active function calls leading to your current position.
    • Navigating the call stack helps you trace the execution path and identify where things might be going wrong. Managing your debugging session effectively includes knowing how to restart the program and exit when you're finished.

    Tips:

    • Use the command that restarts the program while preserving your breakpoints and current settings.
    • There's a command to list all active breakpoints (including breakpoints for runtime and unrecoverable errors), which helps you verify they remain after restarting.
    • To exit the debugger, use the appropriate command to return to the shell. Don't use Ctrl-Cor similar.
  3. Challenge

    Identifying the Bug

    When debugging, efficiency is important. Instead of stepping through each line of code, it's often more effective to jump directly to the point where an issue is likely occurring.

    Conditional breakpoints are a powerful feature that allow you to pause execution only when specific conditions are met, saving time and simplifying the debugging process.

    You can set a conditional breakpoint using the condition command, which lets you specify a boolean expression that must evaluate to true for the breakpoint to trigger. Here's how to do it:

    1. Set a Breakpoint: First, set a breakpoint at the desired location using the break command. For example:

      break main.go:10
      
    2. Add a Condition: After setting the breakpoint, add a condition to it using the condition command. The syntax is:

      condition <breakpoint ID> <boolean expression>
      

      For example, if you want the breakpoint to trigger only when the variable x equals 5, you would use:

      condition 1 x == 5
      

      Here, 1 is the ID of the previously set breakpoint.

    This way, when you resume program execution, the debugger will only stop at the conditional breakpoint if the specified condition is met.

    Alternatively, starting from Delve 1.23.0, you can combine these steps into one command by specifying the condition directly when setting the breakpoint. This is the syntax:

    break <location> if <condition>
    

    For example:

    break main.go:10 if x == 5
    

    To view all active breakpoints and their conditions, you can use the breakpoints command:

    breakpoints
    

    In any case, once you reach a breakpoint, you can inspect the current values of variables and expressions to understand the program state. Use the print command, followed by the variable or expression you want to check:

    print <variable>|<expression>
    

    By inspecting variables at the point of failure, it becomes easier to identify incorrect values or faulty logic.

    In the program you're working on, you have identified that the error occurs in the calculateAverage function, inside the loop, on line 16.

    In the next tasks, you'll apply the above commands to efficiently locate and understand the bug in the program. Remember, using conditional breakpoints allows you to pause execution precisely when certain conditions are met, making debugging more efficient. Examining variable values at critical points in your code helps you understand what's causing errors.

    Tips:

    • Use the command that allows you to print the value of a variable or expression.
    • Remember that accessing an array or slice with an index equal to its length will result in an "index out of range" error.
    • Attempting to access the element at a specific index can help you observe the error firsthand.
  4. Challenge

    Fixing the Bug

    After identifying the cause of the error using the debugger, it's time to fix the bug in the code. The issue lies in the loop condition within the calculateAverage function:

    for i := 0; i <= len(nums); i++ {
       // ...
    }
    

    This loop iterates from i = 0 up to and including i = len(nums), which exceeds the valid index range for the nums slice. In Go, slices are zero-indexed, and the valid indices range from 0 to len(nums) - 1.

    Attempting to access nums[len(nums)] results in an "index out of range" error because it tries to access an element beyond the slice's bounds.

    Off-by-one errors are a frequent source of bugs, especially in loops. It's important to ensure loop conditions correctly reflect the valid range of indices to prevent runtime errors.

    In the next task, you'll fix the bug to allow the program to run without errors.

  5. Challenge

    Verifying the Fix

    After fixing a bug, it's important to verify that your changes have resolved the issue without introducing new ones. Verification ensures that the program now behaves as expected and that the original problem has been effectively addressed.

    In the next task, using the Delve debugger, you'll verify that the bug has been fixed and that the program now calculates the average correctly.

  6. Challenge

    Conclusion

    Congratulations on successfully completing this Code Lab!

    You have learned how to use the Delve CLI to debug Go applications, set breakpoints, navigate through code, inspect variables, and fix bugs efficiently. ---

    Further Exploration

    Delve offers many more commands and features to enhance your debugging experience. Here are some additional commands you might find useful:

    • clear: Removes a breakpoint
    • goroutines: Lists all goroutines
    • threads: Lists all threads
    • sources: Lists source files
    • vars: Lists package variables

    To learn more about any command, you can type:

    help <command>
    

    For comprehensive information and advanced usage, refer to the Delve documentation. ---

    Keep Practicing and Learning

    Debugging is a critical skill in software development. The more you practice using tools like Delve, the more efficient and effective you'll become at identifying and resolving issues in your code.

    If you're interested in further honing your Go skills or exploring more topics, Pluralsight offers several excellent courses in the following path:

    These courses cover many aspects of Go programming.

    For Delve, Pluralsight offers two excellent courses:

    Check them out to continue your learning journey in Delve!

Esteban Herrera has more than twelve years of experience in the software development industry. Having worked in many roles and projects, he has found his passion in programming with Java and JavaScript. Nowadays, he spends all his time learning new things, writing articles, teaching programming, and enjoying his kids.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.