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.
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 -vBenchmark
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=3pprof
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/profileGenerate 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Xiao Lou's Tech Notes
Backend technology sharing, architecture design, performance optimization, source code reading, troubleshooting, and pitfall practices
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
