Generating Stack Traces in Go

Mar 19 2014

The ability to generate a stack trace can prove to be very useful, especially when writing log files. The Go language's runtime package provides a helper for generating a stack trace. Here's how to use it.

Simply put, you can grab a stack trace from just about anywhere in a Go program. Import the runtime package, create a []byte to use as a buffer, and then call runtime.Stack() :

import ( "runtime" "fmt" ) func main () { trace := make ([] byte , 1024 ) count := runtime . Stack ( trace , true ) fmt . Printf ( "Stack of %d bytes: %s" , count , trace ) }

The above will print a simple stack trace. Note that the second argument to runtime.Stack() is a boolean flag. If true , every running go routine will also dump a stack. If false, only the current go routine will dump a stack trace.

More often, it is useful to print a stack trace as a response to an error or panic. Here's a more complex example that shows not only the stack trace gathering, but how it might be employed in response to a panic() .

package main import ( "runtime" "fmt" ) func main () { outer () } func outer () { inner () } func inner () { defer func () { if err := recover (); err != nil { trace := make ([] byte , 1024 ) count := runtime . Stack ( trace , true ) fmt . Printf ( "Recover from panic: %s

" , err ) fmt . Printf ( "Stack of %d bytes: %s

" , count , trace ) } }() panic ( "Fake error!" ) }

To make the trace a little more interesting, I artificially added some empty layers. In a nutshell, main() calls outer() , which calls inner() , which defers an panic handler and then panics.

The panic handler then calls recover() and, if there is a panic to recover from, prints the panic message along with a stack trace. Here's what it looks like when we run it: