% Debugging Go Programs % Tom Arrell % Thursday 28th May – Golang Meetup – SumUp
- Senior Backend Engineer @ SumUp
- Logistics Squad
- twitter: twitter.com/tom_arrell
- github: github.com/tomarrell
:::incremental
- Go at SumUp
- Go in Logistics
- Why we're moving to Go
- Debugging...
- Primitive
- GDB
- Delve
- Scenarios... :::
- Adopted within the last 2 years
- Mainly used for tooling
- First services written ~1 year ago
- Now migrating to Go for new services
- Deployed to Kube
- Joined around ~6 months ago
- Legacy Python scripts
- Lack of monitoring
- Email alerts
- Git clone deployment
- Replaced with Go services
- Deployed to Kubernetes
- Prometheus, Sentry, OpsGenie
- 2 engineers with no prior Go experience brought up to speed
All non-trivial abstractions, to some degree, are leaky.
– Joel Spolsky
We'll take a look at a few contrived scenarios, and how we might be able to get some more insight with as little (or as much) effort as possible.
If you dive into the bug, you tend to fix the local issue in the code, but if you think about the bug first, how the bug came to be, you often find and correct a higher-level problem in the code that will improve the design and prevent further bugs.
– Rob Pike
fmt.Println() is the most universal, and all powerful debugger. Fight me.
– Me, circ. now
package main
import "fmt"
func main() {
fmt.Println("HERE")
go func() {
fmt.Println("Why are you not running?!")
}()
fmt.Println("HERE 2")
}- Ok if you're using CGO
- Not so ok if you're writing plain Go
- Defer statements
- The scheduler, context switching
- Custom type defs of builtin types
- Some identifiers
- Dedicated debugger for Go programs
- Supports debugging:
- Running processes
- Examining core dumps
- Built from scratch programs
- Tests
- Tracing
...ignoring this prohibition [of data races] introduces a practical risk of future miscompilation of the program.
– Hans-J. Boehm
No race is a safe race.
– Me, just now
Build your program with the -race flag.
Good idea to run your tests with this flag enabled.
Warning: The race detector is not infallible, and it may possibly miss certains cases. However, it will never report false positives.
Also.
$ go test -race mypkg // check for races during tests
$ go build -race mycmd // build a binary with R.D.
$ go run -race mysrc.go // immediate run with R.D.Are you getting values back from your function that you don't expect?
Do you want to know which defer statements are being called?
The Go objdump tool displays the x86 assembly in AT&T syntax, whereas Delve displays it in Intel syntax.
- SP: Stack pointer: top of stack.
Sometimes our application has already crashed and we'd like to get a better idea about the root cause.
One possible tool in our investigative toolbox are core dumps.
ulimit -c unlimited # Remove core dump size limit- Core dump: A memory snapshot of a process, usually after a crash.
Slightly more nuanced, may only become a problem over time.
- Prometheus client, exposes heap information
- Use for heap size monitoring over time
- pprof
- Use for heap inspection of running process to find problem objs
Heap profiling with pprof.
go tool pprof localhost:8080/debug/pprof/heap
> web
> topVery hard to debug.
pprof blocking profile not useful for deadlocked routines, but useful for finding contentious resources in your program.
pprof lets you inspect the state of each goroutine in your program.
To get source annotated view of all goroutines in package pkg.
go tool pprof localhost:8080/debug/pprof/goroutine
> list [pkg]Alternatively, you can look at the full goroutine stack dump using:
curl localhost:8080/debug/pprof/goroutine?debug=2
- Debug your test binaries as well
runtime.Breakpoint()- Checkpoints let you restart the program from a specific point
- Linux only
"Use the right tool for the job."
– Someone, I'm pretty sure
--
fin
Questions?




