Golang 支持使用 GDB 来进行调试,这与 C 语言几乎是一致的。但 GDB 是一个通用性调试工具,不非常能直接地反映出 Golang 的特点,例如:goroutine 语句的调试。所以,推荐使用 delve(https://github.com/go-delve/delve),可以理解为是 Golang 版本的 GDB,使用方式大致与 GBD 一致。
dlv 和 gdb 也有着不足的地方,比如:
- dlv 的 print 不支持十六进制打印,gdb 就可以 p /x number。
- dlv 不支持变量、函数名的自动补全
- dlv 的 on 功能与 gdb 的 commands 类似,可是 dlv 只支持 print, stack and goroutine 三个命令,不支持 continue。
安装:
go get -u github.com/derekparker/delve/cmd/dlv
help:
Usage:
dlv [command]
Available Commands:
attach Attach to running process and begin debugging.
connect Connect to a headless debug server.
core Examine a core dump.
debug Compile and begin debugging main package in current directory, or the package specified.
exec Execute a precompiled binary, and begin a debug session.
help Help about any command
run Deprecated command. Use 'debug' instead.
test Compile test binary and begin debugging program.
trace Compile and begin tracing program.
version Prints version.
其中,delve 3 种常见的调试模式为:
- debug 模式:调试源代码。
- exec 模式:调试二进制执行文件。
- attach 模式:调试远程进程。
dlv debug
编译一个临时可执行文件,然后启动调试,类似与 go run 指令。是最简单的模式,常见于调试小型程序。
执行指令:
dlv debug main.go
dlv exec
编译选项:关闭内联优化。
go build -gcflags=all="-N -l"
执行指令:
dlv exec ./HundredsServer ## 直接启动调试
dlv exec ./HundredsServer -- -port 8888 -c /home/config.xml ## 后面加 CMD 参数启动调试
相对的,如果在生产环境中不希望二进制文件被调试,则使用编译选项:
go build -ldflags "-s -w"
# -s:去掉符号信息。
# -w:去掉 DWARF 调试信息。
dlv attach
跟踪调试一个正在运行中的程序。
执行指令:
dlv attach $PID ## 后面的进程的 ID
dlv test
用来调试测试代码,因为测试代码都是某一个包里面,所以 dlv test 是以包为单位的。
dlv test $packname ## 包名
调试指令
- 断点:程序运行的断点。
- 跟踪点:将消息打印到 “输出” 窗口,跟踪点的作用像这种编程语言中的一个临时跟踪语句,且不会暂停代码的执行。
(dlv) help
The following commands are available:
args -------------------------------- 打印函数参数。
break (alias: b) -------------------- 设置断点,例如:b 包名.函数名,或 b 文件名:行数。
breakpoints (alias: bp) ------------- 显式断点清单。
call -------------------------------- Resumes process, injecting a function call (EXPERIMENTAL!!!)
check (alias: checkpoint) ----------- 在当前位置创建检查点。
checkpoints ------------------------- 打印现有检查点的信息。
clear ------------------------------- 删除断点。
clear-checkpoint (alias: clearcheck) 删除检查点。
clearall ---------------------------- 删除多个断点。
condition (alias: cond) ------------- 设置断点条件。
config ------------------------------ 更改配置参数。
continue (alias: c) ----------------- 运行到断点或程序终止。
disassemble (alias: disass) --------- 反汇编程序。
down -------------------------------- 下移当前帧。
edit (alias: ed) -------------------- Open where you are in $DELVE_EDITOR or $EDITOR
exit (alias: quit | q) -------------- Exit the debugger.
frame ------------------------------- 设置当前帧,或在其他帧上执行命令。
funcs ------------------------------- 打印函数列表。
goroutine --------------------------- 显示或更改当前 goroutine
goroutines -------------------------- List program goroutines.
help (alias: h) --------------------- Prints the help message.
list (alias: ls | l) ---------------- Show source code.
locals ------------------------------ 打印局部变量。
next (alias: n) --------------------- 转到下一行。
on ---------------------------------- 在命中断点时执行命令。
print (alias: p) -------------------- Evaluate an expression.
regs -------------------------------- Print contents of CPU registers.
restart (alias: r) ------------------ Restart process from a checkpoint or event.
rewind (alias: rw) ------------------ 向后运行,直到断点或程序终止。
set --------------------------------- 更改变量的值。
source ------------------------------ Executes a file containing a list of delve commands
sources ----------------------------- 打印源文件列表。
stack (alias: bt) ------------------- 打印堆栈跟踪。
step (alias: s) --------------------- 单步执行程序。
step-instruction (alias: si) -------- 单步单 CPU 指令。
stepout ----------------------------- 跳出当前函数。
thread (alias: tr) ------------------ 切换到指定的线程。
threads ----------------------------- 打印每个跟踪线程的信息。
trace (alias: t) -------------------- 设置跟踪点。
types ------------------------------- 打印类型列表。
up ---------------------------------- 将当前帧上移。
vars -------------------------------- 打印包变量。3
whatis ------------------------------ 打印表达式的类型。