Debug
Goals
- Find the root cause of test failures, build errors, or runtime bugs.
- Use Go-native tooling for investigation.
- Produce a minimal reproduction and targeted fix.
Toolchain
| Tool | Purpose |
|---|---|
go test ./... -v |
Run all tests with verbose output |
go test ./... -run TestName |
Run a specific test by name |
go test ./... -count=1 |
Bypass test cache |
go build ./... |
Check compilation across all packages |
go vet ./... |
Static analysis for common bugs |
gofmt -l . |
Find files with formatting issues |
gofmt -d . |
Show formatting diffs |
dlv test ./pkg/... -- -test.run TestName |
Debug a specific test interactively |
go test -race ./... |
Detect data races |
go test -coverprofile=coverage.out ./... |
Generate coverage profile |
Quick Triage
- Build check:
go build ./...— does it compile? - Vet check:
go vet ./...— any static analysis issues? - Format check:
gofmt -l .— any formatting violations? - Test run:
go test ./... -v -count=1— which tests fail? - Targeted test:
go test -v -run TestFailingName ./path/to/pkg/
Investigation Flow
- Reproduce the failure:
- Run the exact failing command and capture full output.
- Note the package, test name, and error message.
- Isolate the scope:
- Run only the failing package:
go test -v ./internal/failing/... - Run only the failing test:
go test -v -run TestName ./internal/failing/
- Run only the failing package:
- Read the code:
- Open the test file and the code under test.
- Trace the execution path from the test assertion backward.
- Check dependencies:
go mod verify— are module checksums intact?go mod tidy— are imports consistent with go.mod?
- Add diagnostic output (temporary):
- Use
t.Logf(...)in tests for debug output (visible with-v). - Use
fmt.Fprintf(os.Stderr, ...)for non-test code. - Remove all diagnostic code before committing.
- Use
- Fix and validate:
- Apply the minimal fix.
- Run
go build ./... && go test ./... -count=1 && go vet ./... - Run
gofmt -w .if formatting changed.
Common Failure Patterns
| Symptom | Likely cause | Action |
|---|---|---|
undefined: |
Missing import or unexported name | Check imports and capitalization |
cannot use X as type Y |
Interface mismatch or wrong type | Check method signatures |
--- FAIL: TestX |
Test assertion failure | Read expected vs actual values |
panic: runtime error |
Nil pointer, index out of range | Add nil checks, bounds checks |
go.sum mismatch |
Tampered or stale module cache | go mod tidy && go mod verify |
| Data race detected | Concurrent access without sync | Add mutex or use channels |
Notes
- Always use
-count=1to bypass test cache when debugging. - Prefer
go test -vfor full output includingt.Logstatements. - Remove all temporary debug code before the final commit.
- If a test is flaky, run it multiple times:
go test -count=5 -run TestFlaky ./...