Golang 调试工具——dlv
简单介绍了一些 dlv 的命令及其含义。
Delve 是 Go 编程语言的调试器。
安装
-
下载dlv
git clone https://github.com/go-delve/delve.git $GOPATH/src/github.com/go-delve/delve
或者
go get github.com/derekparker/delve/cmd/dlv
2. 安装
cd $GOPATH/src/github.com/go-delve/delve make install
-
验证是否安装成功
$ dlv version Delve Debugger Version: 1.7.2 Build: $Id: 5b6f24e7fbcad3fe3bc574d3763b2f20afa1d6a1 $
使用手册
获取帮助 执行 dlv -h
执行 dlv help + 具体命令 来查看详细说明,
例如:dlv help attach 来查看 attach 的使用方式。
进入调试模式
-
dlv attach <pid>:对正在运行的进程直接进行调试(pid为进程号): -
dlv debug [package]:在禁用优化的情况下编译程序,启动并 attach 到它。 -
dlv exec <exe>:执行预编译的二进制文件并开始 debug 会话。这个执行的二进制文件在其编译是需要禁止优化的。具体操作在 补充内容 中有写。
-
dlv core <executable> <core> [flags]:Examine a core dump (only supports linux and windows core dumps). 不是很懂。 -
dlv test [package]:用于调试 test 文件的。dlv trace追调用轨迹 dlv trace [package]:可以追踪代码中函数的调用轨迹。package main import ( "fmt" "time" ) func Test() { fmt.Println("hello") time.Sleep(1000 * 1000 * 100) } func Test2() { fmt.Println("world") time.Sleep(1000 * 1000 * 100) } func main() { for i := 0; i < 2; i++ { go Test() go Test2() } time.Sleep(1000 * 1000 * 2000) fmt.Println("end") }
这部分代码,我们创建了两个函数,Test 和 Test2。同时在主函数中创建四个协程来执行它们。
$ dlv trace hello.go Test
goroutine(19): main.Test2()
goroutine(21): main.Test2()
goroutine(18): main.Test()
world
hello
world
goroutine(20): main.Test()
hello
=> ()
=> ()
=> ()
=> ()
end
Trace 命令可以添加正则表达式的参数,在这个命令中添加的是 Test,所以除了Test,Test2也被追踪到了。
补充内容
禁止优化:原因是 golang 在编译过程中会对某些代码进行优化,这可能会导致实际运行代码与源代码不匹配的情况,那这部分不匹配的代码(如被内联优化的代码)就没法对其进行 debug。所以我们在debug时,通常情况需要禁止优化。
Golang 在编译时,也提供了进展优化的参数: go build -gcflags="all=-N -l" -o bin/app
-
go build 可以用 -gcflags 给 go 编译器传入参数,也就是传给
go tool compile的参数,因此可以用go tool compile --help查看所有可用的参数。 -
"all=-N -l" 表示对所有包的编译应用 -N 和 -l。 执行
go tool compile --help可以看到 -N 和 -l 的作用:-N disable optimizations # 禁用优化 -l disable inlining # 禁用内联优化。
使用 -m 可以查看编译器优化决策
调试模式基本命令
常用命令
- b(break):
break [name] [linespec]设置一个断点。
示例如下:
b Test
b test.go:13
-
r(restart):重启当前进程。
如果刚执行了
dlv debug hello.go无需执行此命令。如果进程已经结算或需要重新开始,则需要执行r。 -
c(continue):继续执行到下一个断点处。
-
bp(breakpoints):查看所有断点。
-
on:
on <breakpoint name or id> trace: 当运行到某断点时执行相应命令。
示例:
on 3 p i
指的是对运行到断点3的时候打印变量 i。
- cond(condition):有条件的断点。针对某个断点,只有表达式成立才会被中断。
示例如下:
condition 3 i==1
- n(next): 逐行执行代码,不进入函数内。
- s(step): 逐行执行代码,遇到函数会跳进内部。
- stepout : 当使用 s 命令进入某个函数后,执行它可跳出函数。
- si(step-instruction) : 单步单核执行代码。
- args : 查看被调用函数所传入的参数值。
- locals: 查看所有局部变量。
- clear: 清除单个断点。
- clearall: 清除多个断点。
- list: 打印当前断点位置的源代码。
- bt: 打印当前栈信息。 多协程调试
- goroutines: 显示所有协程。
- goroutine: 切换协程。 goroutine 7 ##表示切换到 7 号协程上。
其他命令
-
frame:切换栈。
-
regs: 打印寄存器内容。
-
sources:打印所有源代码文件路径。
-
source:执行一个含有dlv命令的文件。
-
trace:类似于打断点,但不会中断,同时会输出一行提示信息。
参考文章:
\