A cross-platform debugger for Go.
godebug
uses source code generation to instrument your program with debugging calls. go tool cover takes a similar approach to code coverage. When you run godebug
, it parses your program, instruments function calls, variable declarations, and statement lines, outputs the resulting code somewhere, and runs it. When this modified code runs, it stops at breakpoints and lets you step through the program and inspect variables.
For more detail, see the end of this README.
godebug
is still very new. File an issue or send me an email if you find any rough edges:
$ go get github.com/mailgun/godebug
Insert a breakpoint anywhere in a source file you want to debug:
_ = "breakpoint"
If the breakpoint is in package main and you don't want to examine any imported packages, you can just run:
$ godebug run gofiles... [arguments...]
If you want to trace the program outside of the main package, list the packages to trace in the -instrument
flag:
$ godebug run -instrument=pkg1,pkg2,pkg3 gofiles... [arguments...]
If you are debugging a test, use 'godebug test':
$ godebug test [-instrument pkgs...]
That's it!
The current commands are:
command | result |
---|---|
h(elp) | show help message |
n(ext) | run the next line |
s(tep) | run for one step |
c(ontinue) | run until the next breakpoint |
l(ist) | show the current line in context of the code around it |
p(rint) [var] | print a variable |
The debugger will attempt to interpret any text that does not match the above commands as a variable name. If that variable exists, the debugger will print it.
Consider this program:
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
Now let's modify it a bit:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
fmt.Println(`-> fmt.Println("Hello, world!")`)
bufio.NewScanner(os.Stdin).Scan()
fmt.Println("Hello, world!")
}
When we run this modified version, we see:
-> fmt.Println("Hello, world!")
And then the program waits for input before proceeding.
We have just implemented a debugger for the first program! It may not seem like much, but this program implements two fundamental debugger behaviors: (1) display the the current state of the program, and (2) do not proceed until instructed by the user. Furthermore, the changes we made were straightforward and easy to automate:
- insert import statements for
bufio
andos
, if not already present. - in
main()
, insert the statementfmt.Println(<quote next line>)
- in
main()
, insert the statementbufio.NewScanner(os.Stdin).Scan()
.
We could do exactly the same thing for any other program with a single-line main function. And it's not hard to see how to generalize this to multiple lines. This, in essence, is what godebug does. Parse source code, insert extra code that implements the behavior of a debugger for that program, output and run the result. godebug handles many more cases than this simple example and implements more interesting debugging behavior, but the principle is exactly the same.