目前,Golang支持的调试器有:
GDB
:Golang最早支持的调试工具,对Golang专有特性缺少很好的支持LLDB
:macOS推荐的标准调试工具,对Golang专有特性缺少很好的支持Delve
:专门为Golang设计开发的调试工具,本身由Golang开发,对Windows平台也提供同样的支持Golang中的条件断点需要使用
delve
来实现。
go get github.com/go-delve/delve/cmd/dlv
sugoi@sugoi:~$ dlv version
Delve Debugger
Version: 1.4.0
Build: $Id: 67422e6f7148fa1efa0eac1423ab5594b223d93b $
sugoi@sugoi:~$ dlv help
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.
Pass flags to the program you are debugging using `--`, for example:
`dlv exec ./hello -- server --config conf/config.toml`
Usage:
dlv [command]
Available Commands:
attach Attach to running process and begin debugging. 可以用来对一个正在运行的进行进行调试.
connect Connect to a headless debug server. 连接到headless调试器.
core Examine a core dump. 用来调试core文件.
debug Compile and begin debugging main package in current directory, or the package specified. 在当前包或者指定的包编译并debug程序.
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. 输出版本信息
Flags:
--accept-multiclient Allows a headless server to accept multiple client connections.
--api-version int Selects API version when headless. (default 1)
--backend string Backend selection (see 'dlv help backend'). (default "default")
--build-flags string Build flags, to be passed to the compiler.
--check-go-version Checks that the version of Go in use is compatible with Delve. (default true)
--headless Run debug server only, in headless mode.
--init string Init file, executed by the terminal client.
-l, --listen string Debugging server listen address. (default "127.0.0.1:0")
--log Enable debugging server logging.
--log-dest string Writes logs to the specified file or file descriptor (see 'dlv help log').
--log-output string Comma separated list of components that should produce debug output (see 'dlv help log')
--only-same-user Only connections from the same user that started this instance of Delve are allowed to connect. (default true)
--wd string Working directory for running the program. (default ".")
Additional help topics:
dlv backend Help about the --backend flag.
dlv log Help about logging flags.
Use "dlv [command] --help" for more information about a command.
这里需要用到的是debug子命令。
进入项目目录,输入dlv debug
这是一个交互式的界面,输入help
命令查看调试过程中可以执行的操作:
sugoi@sugoi:~/go/src/awesomeProject/learndelve$ dlv debug
Type 'help' for list of commands.
(dlv) help
The following commands are available:
args ------------------------ Print function arguments.
break (alias: b) ------------ Sets a breakpoint.
breakpoints (alias: bp) ----- Print out info for active breakpoints.
call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!)
clear ----------------------- Deletes breakpoint.
clearall -------------------- Deletes multiple breakpoints.
condition (alias: cond) ----- Set breakpoint condition.
config ---------------------- Changes configuration parameters.
continue (alias: c) --------- Run until breakpoint or program termination.
deferred -------------------- Executes command in the context of a deferred call.
disassemble (alias: disass) - Disassembler.
down ------------------------ Move the current frame down.
edit (alias: ed) ------------ Open where you are in $DELVE_EDITOR or $EDITOR
exit (alias: quit | q) ------ Exit the debugger.
frame ----------------------- Set the current frame, or execute command on a different frame.
funcs ----------------------- Print list of functions.
goroutine (alias: gr) ------- Shows or changes current goroutine
goroutines (alias: grs) ----- List program goroutines.
help (alias: h) ------------- Prints the help message.
libraries ------------------- List loaded dynamic libraries
list (alias: ls | l) -------- Show source code.
locals ---------------------- Print local variables.
next (alias: n) ------------- Step over to next source line.
on -------------------------- Executes a command when a breakpoint is hit.
print (alias: p) ------------ Evaluate an expression.
regs ------------------------ Print contents of CPU registers.
restart (alias: r) ---------- Restart process.
set ------------------------- Changes the value of a variable.
source ---------------------- Executes a file containing a list of delve commands
sources --------------------- Print list of source files.
stack (alias: bt) ----------- Print stack trace.
step (alias: s) ------------- Single step through program.
step-instruction (alias: si) Single step a single cpu instruction.
stepout (alias: so) --------- Step out of the current function.
thread (alias: tr) ---------- Switch to the specified thread.
threads --------------------- Print out info for every traced thread.
trace (alias: t) ------------ Set tracepoint.
types ----------------------- Print list of types
up -------------------------- Move the current frame up.
vars ------------------------ Print package variables.
whatis ---------------------- Prints type of an expression.
Type help followed by a command for full documentation.
其实有缩写的都是比较常用的。
常用的子命令包括:
命令 | 缩写 | 说明 | 示例 |
---|---|---|---|
break | b | 设置断点 | break [文件名:行数] |
condition | cond | 设置断点的条件 | condition [断点名称/编号] [判断条件](如i==3 ) |
breakpoints | bp | 显示已经设置的断点 | breakpoints |
clear | 删除断点 | bp显示的断点有名称,clear [断点名称] | |
continue | c | 让程序运行到下一个断点处 | continue |
next | n | 单步执行 | next |
step | s | 进入某个函数内部,无法进入goroutine中 | step(在函数入口出执行) |
stepout | so | 退出当前函数,回到进入点 | so |
p | 打印变量的值 | ||
goroutine | gr | 显示当前go协程或切换go协程 | goroutine [协程编号] |
goroutines | grs | 显示全部go协程 | goroutines |
restart | r | 重新运行 | 上次设置的断点依然有效 |
args | 输出函数参数 | ||
locals | 输出函数局部变量 |
主函数代码如下:
package main
import "fmt"
func main() {
nums := make([]int, 5)
for i := 0; i < len(nums); i++ {
nums[i] = i * i
}
fmt.Println(nums)
}
Delve内部为panic()
异常函数设置了断点。
(dlv) bp
Breakpoint runtime-fatal-throw at 0x433f20 for runtime.fatalthrow() /opt/go/src/runtime/panic.go:1158 (0)
Breakpoint unrecovered-panic at 0x433f90 for runtime.fatalpanic() /opt/go/src/runtime/panic.go:1185 (0)
print runtime.curg._panic.arg
在主函数入口处设置断点,输入c
运行代码。
(dlv) b main.main
Breakpoint 1 set at 0x4ad768 for main.main() ./main.go:5
(dlv) bp
Breakpoint runtime-fatal-throw at 0x433f20 for runtime.fatalthrow() /opt/go/src/runtime/panic.go:1158 (0)
Breakpoint unrecovered-panic at 0x433f90 for runtime.fatalpanic() /opt/go/src/runtime/panic.go:1185 (0)
print runtime.curg._panic.arg
Breakpoint 1 at 0x4ad768 for main.main() ./main.go:5 (0)
(dlv) c
> main.main() ./main.go:5 (hits goroutine(1):1 total:1) (PC: 0x4ad768)
1: package main
2:
3: import "fmt"
4:
=> 5: func main() {
6: nums := make([]int, 5)
7: for i := 0; i < len(nums); i++ {
8: nums[i] = i * i
9: }
10: fmt.Println(nums)
(dlv)
组合使用break
和condition
来创建条件断点。
(dlv) b main.go:8
Breakpoint 2 set at 0x4ad7bd for main.main() ./main.go:7
(dlv) cond 2 i==3
(dlv) bp
Breakpoint runtime-fatal-throw at 0x433f20 for runtime.fatalthrow() /opt/go/src/runtime/panic.go:1158 (0)
Breakpoint unrecovered-panic at 0x433f90 for runtime.fatalpanic() /opt/go/src/runtime/panic.go:1185 (0)
print runtime.curg._panic.arg
Breakpoint 1 at 0x4ad768 for main.main() ./main.go:5 (1)
Breakpoint 2 at 0x4ad7bd for main.main() ./main.go:8 (0)
cond i == 3
使用continue
运行到断点2,使用locals
查看当前变量,条件断点生效。
(dlv) c
> main.main() ./main.go:8 (hits goroutine(1):1 total:1) (PC: 0x4ad7db)
3: import "fmt"
4:
5: func main() {
6: nums := make([]int, 5)
7: for i := 0; i < len(nums); i++ {
=> 8: nums[i] = i * i
9: }
10: fmt.Println(nums)
11: }
(dlv) locals
nums = []int len: 5, cap: 5, [...]
i = 3
查看其他信息包括协程额函数栈等。
(dlv) stack
0 0x00000000004ad7db in main.main
at ./main.go:8
1 0x0000000000436438 in runtime.main
at /opt/go/src/runtime/proc.go:203
2 0x0000000000463df1 in runtime.goexit
at /opt/go/src/runtime/asm_amd64.s:1373
(dlv) goroutines
* Goroutine 1 - User: ./main.go:8 main.main (0x4ad7db) (thread 197086)
Goroutine 2 - User: /opt/go/src/runtime/proc.go:305 runtime.gopark (0x4367eb)
Goroutine 3 - User: /opt/go/src/runtime/proc.go:305 runtime.gopark (0x4367eb)
Goroutine 4 - User: /opt/go/src/runtime/proc.go:305 runtime.gopark (0x4367eb)
Goroutine 5 - User: /opt/go/src/runtime/proc.go:305 runtime.gopark (0x4367eb)
[5 goroutines]
(dlv) goroutine
Thread 197086 at ./main.go:8
Goroutine 1:
Runtime: ./main.go:8 main.main (0x4ad7db)
User: ./main.go:8 main.main (0x4ad7db)
Go: /opt/go/src/runtime/asm_amd64.s:220 runtime.rt0_go (0x461d64)
Start: /opt/go/src/runtime/proc.go:113 runtime.main (0x436270)
(dlv)quit