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:
You'll need tell the go tool not to optimize and keep variable information:
$ go build -gcflags "-N -l" manual-bp
$ gdb manual-bp
When you hit the breakpoint, you'll be in assembly code. Exit two functions to get to your code
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
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.