Debugging Go HTTP Handlers with Delve and Postman

Debugging Go HTTP Handlers with Delve and Postman

Muhammad Hafizh Roihan
4 min read

1. The Problem with fmt.Println Debugging

Every Go developer has done it — sprinkling fmt.Println calls throughout an HTTP handler to figure out what’s going wrong with an incoming request. It works, but it’s slow: change code, restart server, resend the request, read the output, repeat.

When you’re dealing with complex handler logic — parsing request bodies, chaining middleware, hitting a database — this cycle gets painful fast. What you actually want is to pause execution mid-request, inspect the live state of every variable, and step through the code line by line.

That’s exactly what Delve gives you.

2. How It Works

The approach is simple:

  1. Configure VS Code to launch your Go server through Delve
  2. Press F5 — VS Code compiles your code and starts the server with the debugger attached
  3. Set a breakpoint inside your HTTP handler
  4. Send a request from Postman
  5. VS Code pauses at the breakpoint — inspect variables, step through logic

No code changes needed in your application, and no manual terminal commands. VS Code handles everything through the Go extension.

3. Prerequisites

  • Delve installed:
    go install github.com/go-delve/delve/cmd/dlv@latest
  • VS Code with the Go extension
  • Postman

4. The Example Project

We’ll use a minimal HTTP server with a single POST /users endpoint:

// main.go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

type CreateUserRequest struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

type CreateUserResponse struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

func main() {
	http.HandleFunc("/users", handleCreateUser)
	fmt.Println("Server running on :8080")
	http.ListenAndServe(":8080", nil)
}

func handleCreateUser(w http.ResponseWriter, r *http.Request) {
	var req CreateUserRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "invalid request body", http.StatusBadRequest)
		return
	}

	// Business logic would go here
	resp := CreateUserResponse{
		ID:    1,
		Name:  req.Name,
		Email: req.Email,
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(resp)
}

5. Configuring VS Code

Create a .vscode/launch.json file in your project root:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to Delve",
      "type": "go",
      "request": "launch",
      "mode": "debug",
      "program": "${workspaceFolder}",
      "cwd": "${workspaceFolder}"
    }
  ]
}

What the key fields mean:

FieldValueDescription
request"launch"VS Code starts the process — no manual server needed
mode"debug"Compile and run under Delve
program${workspaceFolder}Run the main package at the project root

Then to start the debug session:

  1. Open the Run and Debug panel (Ctrl+Shift+D)
  2. Select “Attach to Delve” from the dropdown
  3. Press F5 (or click the green play button)

VS Code will compile your code and start the HTTP server with Delve attached. You’ll see the debug toolbar appear at the top and your server logs in the Debug Console.

7. Set a Breakpoint

Open main.go and click the gutter (the space to the left of the line numbers) on the line inside handleCreateUser where you want to pause. A red circle will appear.

For this example, set the breakpoint on the line right after the decode block — where business logic begins:

func handleCreateUser(w http.ResponseWriter, r *http.Request) {
	var req CreateUserRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "invalid request body", http.StatusBadRequest)
		return
	}

	// 👈 set breakpoint here
	resp := CreateUserResponse{

8. Send the Request from Postman

In Postman, send a POST request to http://localhost:8080/users with this body:

{
  "name": "Alice",
  "email": "alice@example.com"
}

The moment the request hits the handler, VS Code will pause at your breakpoint. Postman will show the request as pending — it’s waiting for the handler to complete.

Demo: Postman request triggering a breakpoint pause in VS Code with Delve

9. Inspect and Step Through

VS Code paused at breakpoint inside handleCreateUser — Variables panel showing req.Name and req.Email

With execution paused, you can:

  • Variables panel (left sidebar) — see the current value of req, w, r, and every local variable in scope
  • Watch panel — add expressions like req.Name to track specific values
  • Step Over (F10) — execute the current line and move to the next
  • Step Into (F11) — dive into a function call
  • Continue (F5) — resume execution until the next breakpoint

Once you hit Continue, the handler finishes and Postman receives the response.

10. Stopping the Session

When you’re done, click the red square in the debug toolbar (or press Shift+F5). VS Code stops the Delve process and the HTTP server along with it.

To debug again, just press F5 — VS Code recompiles and restarts from scratch.

Summary

StepWhat you do
ConfigureCreate .vscode/launch.json (see section 5)
StartVS Code → Run and Debug → F5
Set breakpointClick gutter next to the line in your handler
TriggerSend request from Postman
InspectUse Variables / Watch / Step controls in VS Code
ResumePress F5 — Postman gets the response
StopShift+F5 — stops both Delve and the HTTP server

That’s the full flow. Once you’ve done it once, it becomes a natural part of the debugging loop — much faster than print-statement debugging for anything more complex than a trivial handler.