Master Go Testing, Benchmarking, and Profiling: From Unit Tests to dlv Debugging

This guide shows how Go simplifies unit testing, benchmarking, CPU profiling with pprof, and live debugging using dlv, providing step‑by‑step code examples, command‑line usage, and visual analysis techniques for backend developers.

Xiao Lou's Tech Notes
Xiao Lou's Tech Notes
Xiao Lou's Tech Notes
Master Go Testing, Benchmarking, and Profiling: From Unit Tests to dlv Debugging

Unit Testing

In Go, unit testing is built‑in and requires no external library. A test file named cal_test.go with functions prefixed by TestXxx is automatically discovered.

package unit

func add(a int, b int) int {
    return a + b
}

func sub(a int, b int) int {
    return a - b
}
package unit

import (
    "github.com/stretchr/testify/assert"
    "testing"
)

func TestAdd(t *testing.T) {
    assert.Equal(t, 10, add(5, 5))
}

func TestSub(t *testing.T) {
    assert.Equal(t, 0, sub(5, 5))
}

Run the tests with:

go test --cover cal_test.go cal.go -v

Benchmark

Go also provides built‑in benchmarking. Adding a BenchmarkAdd function to the same test file runs a loop measuring performance.

package unit

import (
    "github.com/stretchr/testify/assert"
    "testing"
)

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        add(5, 5)
    }
}

Execute with:

go test -bench=. -cpu=4 -count=3

pprof

Go’s net/http/pprof package enables CPU, memory, and lock profiling similar to Java’s async‑profiler. Import the package and start an HTTP server.

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
    _ "net/http/pprof"
)

func main() {
    go func() {
        err := http.ListenAndServe("0.0.0.0:6060", nil)
        if err != nil {
            fmt.Println("failed to start pprof goroutine:", err)
        }
    }()

    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("localhost:8000", nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
    time.Sleep(1 * time.Second)
    eat()
    t := time.Now().Unix()*2 + 1000000
    fmt.Fprintf(w, "URL.Path = %q; time = %d
", r.URL.Path, t)
}

func eat() {
    loop := 10000000000
    for i := 0; i < loop; i++ {
        // do nothing
    }
}

Collect a profile with:

go tool pprof http://127.0.0.1:6060/debug/pprof/profile

Generate load (e.g., curl http://127.0.0.1:8000/hello) and after a while the tool saves a compressed profile file, which can be inspected with go tool pprof -http=":8080" <profile_file> or visualized via a web UI (Graphviz may be required).

dlv

When pprof is not enabled, the Delve debugger ( dlv) can attach to a running Go process to inspect goroutines. The Go version of the binary and Delve must match.

package main

import (
    "fmt"
    "sync"
)

func main() {
    go count()
    go wait()
    wait()
}

func count() {
    count := 0
    for {
        count++
        if count%1000000000 == 0 {
            fmt.Println("I'm a running routine")
        }
    }
}

func wait() {
    wg := sync.WaitGroup{}
    wg.Add(1)
    wg.Wait()
}

Run the program and attach with dlv attach <pid> to view goroutine states.

Conclusion

Go bundles essential testing, benchmarking, and profiling tools, lowering the entry barrier for newcomers while providing powerful capabilities for backend developers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendGopprofunit testingbenchmarkprofilingdlv
Xiao Lou's Tech Notes
Written by

Xiao Lou's Tech Notes

Backend technology sharing, architecture design, performance optimization, source code reading, troubleshooting, and pitfall practices

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.