I Python we do it with pdb.set_trace(), in Go we'll need to work a little harder. The main idea is that breakpoints are special signal called SIGTRAP.
Here's the code to do this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// "Manual" breapoing in go | |
// Compile with | |
// go build -gcflags "-N -l" manual-bp.go | |
// Then | |
// gdb manual-bp | |
// (gdb) run | |
// When you hit breakpoint, call "fin" twice to get to the current location | |
// (gdb) fin | |
// (gdb) fin | |
// After that it's usuall gdb commands | |
// (gdb) p i | |
// $1 = 3 | |
package main | |
import ( | |
"fmt" | |
"syscall" | |
) | |
func foo() { | |
for i := 0; i < 5; i++ { | |
if i == 3 { // Some complicated condition | |
// Initiate a breakpoint | |
syscall.Kill(syscall.Getpid(), syscall.SIGTRAP) | |
} | |
fmt.Printf("i = %d\n", i) | |
} | |
} | |
func main() { | |
foo() | |
} |
$ go build -gcflags "-N -l" manual-bp
$ gdb manual-bp
(gdb) run
When you hit the breakpoint, you'll be in assembly code. Exit two functions to get to your code
(gdb) fin
(gdb) fin
Then you'll be in your code and can run gdb commands
(gdb) p i
$1 = 3
This scheme also works with delve
$ dlv debug manual-bp.go
(dlv) c
Sadly delve don't have "fin" command so you'll need to hit "n" (next) until you reach your code.
That's it, happy debugging.
Oh - and in the very old days we did about the same trick in C code. There we manually inserted asm("int $3)" to the code. You can do with with cgo but sending a signal seems easier.