delve
is a debugger developed in Golang
and also dedicated to help trouble-shooting Golang
programs (Home page is here). Though it is still in pre-1.0
release, I think it is stable enough for daily use. BTW, if you find some bugs, you can report it to developers and help to make delve
more stronger! P.S., Albeit fmt.Print
buddies are useful in most cases, I strongly recommend you try to usedelve
to inspect the internal mechanism of your code, because it can help you know Golang
deeper, not just superficial stuff.
Installing delve
is very simple: taking Linux
platform as an example, it is no different from setting up other Golang
projects, just “go get
” is enough:
go get github.com/derekparker/delve/cmd/dlv
Now, in $GOPATH/bin
, there is an extra dlv
executable binary file (Notice: the project is named delve
, while the executable file is calleddlv
. I even made a foolish mistake when began to use it).Run dlv
command, and it will show you a detailed manual of delve
:
# dlv
Delve is a source level debugger for Go programs.
Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.
The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.
Usage:
dlv [command]
Available Commands:
version Prints version.
run Deprecated command. Use 'debug' instead.
debug Compile and begin debugging program.
......
Let’s check this artificial Hello.go
program:
package main
import "fmt"
func main() {
var s []byte
s = append(s, []byte("Hello, Debugging!")...)
fmt.Println(string(s))
}
Use delve
to debug it:
# dlv debug Hello.go
Type 'help' for list of commands.
(dlv) help
The following commands are available:
help (alias: h) ------------- Prints the help message.
break (alias: b) ------------ Sets a breakpoint.
trace (alias: t) ------------ Set tracepoint.
restart (alias: r) ---------- Restart process.
continue (alias: c) --------- Run until breakpoint or program termination.
step (alias: s) ------------- Single step through program.
step-instruction (alias: si) Single step a single cpu instruction.
next (alias: n) ------------- Step over to next source line.
threads --------------------- Print out info for every traced thread.
thread (alias: tr) ---------- Switch to the specified thread.
......
If you are familiar with gdb
, you will find the commands are very similar, and I promise you can master delve
soon.
An interesting thing is that the delve
doesn’t provide start
command which gdb
offers, so you should try to set breakpoints first, then run continue
command:
(dlv) b Hello.go:8
Breakpoint 1 set at 0x4011ea for main.main() ./Hello.go:8
(dlv) c
> main.main() ./Hello.go:8 (hits goroutine(1):1 total:1) (PC: 0x4011ea)
3: import "fmt"
4:
5: func main() {
6: var s []byte
7: s = append(s, []byte("Hello, Debugging!")...)
=> 8: fmt.Println(string(s))
9: }
(dlv) p s
[]uint8 len: 17, cap: 32, [72,101,108,108,111,44,32,68,101,98,117,103,103,105,110,103,33]
(dlv) goroutines
[4 goroutines]
* Goroutine 1 - User: ./Hello.go:8 main.main (0x4011ea)
Goroutine 2 - User: /usr/local/go/src/runtime/proc.go:263 runtime.gopark (0x42a153)
Goroutine 3 - User: /usr/local/go/src/runtime/proc.go:263 runtime.gopark (0x42a153)
Goroutine 4 - User: /usr/local/go/src/runtime/mfinal.go:144 runtime.runfinq (0x413f80)
Cool! Isn’t it? Now You can observe almost everything you want to know about your program.
Happy Debugging! Happy delving!