Delve 使用
Delve 是一个 Golang 的调试工具,比 GDB 要好用很多,能支持协程的调试。使用的时候可以直接运行程序调试,也可以 attach 到一个正在运行中的程序。
安装
Delve 的安装很简单,它本身也是 go 写的。
go get -u github.com/derekparker/delve/cmd/dlv
运行调试
写一个简单的 go 程序
package main
import "fmt"
func main() {
a := 1
fmt.Println(a)
b := a + 1
fmt.Println(b)
}
然后使用 Delve 的 debug 模式运行这个程序
$ dlv debug ./1.go
也可以输入 help 来查看下帮助文档
一般调试开始是使用 b 设置一个断点,然后用 c 运行到断点处,接下来使用 n 或者 s 来执行。
设置断点有两种方式
一种是类似 b main.main 的指定某个函数
另一种是 b 1.go:6 指定文件的行
其它常用命令
print(别名 p) 输出变量信息
args 打印出方法的所有参数信息
locals 打印所有的本地变量
使用 Delve 附加在运行的程序上调试
首先查出运行的程序的进程号,比如 123
然后执行 dlv attach 123 就可以进行调试了。
将参数传递给二进制文件
如果这样会报错
dlv --listen=:5432 exec /mypath/binary --config=config.toml
解决方案
添加--
来告诉dlv
所有后续参数都应原样传递给二进制文件,而无需尝试解析它们
dlv --listen=:5432 exec /mypath/binary -- --config=config.toml
Server 形式调试
_dlv _--listen=:2345 --headless=true --api-version=2 --accept-multiclient exec binnaryName
_dlv _--listen=:2345 --headless=true --api-version=2 --accept-multiclient attach $PID
错误处理
打断点提示 executable doesn’t contain debug infomation
如果断点打不上,提示 executable doesn’t contain debug infomation for xxxx.go。这种情况一般是这段代码不会被调用到。
报错 could not attach to pid #: could not open debug info
从 ldflags 中去掉 “-w -s”。
加上 -gcflags='all=-N -l'
报错 stub exited while waiting for connection: exit status 0
这个具体原因不知道, 可以按下面的步骤一步步来处理。
Enable devToolsSecurity
sudo /usr/sbin/DevToolsSecurity --enable
添加用户权限
sudo dscl . append /Groups/_developer GroupMembership <your username>
使用脚本
首先如果电脑上有防火墙,需要打开防火墙允许 dlv 命令运行。
解决这个问题的办法是使用 sudo 运行 dlv 命令。
Github issue 里说的是替换 /Applications/GoLand.app/Contents/plugins/go/lib/dlv/mac/dlv 这个 Goland 的命令,但是我发现我的 Goland 使用的是我本地的命令(这个在执行 debug 时可以看到使用的哪里的 dlv)。
所以我写了一个 shell 脚本来使用 sudo 运行 dlv。
echo my-password| sudo -S -E my-dlv-command ${@}
然后将这个脚本做一个软连接放到 PATH 里,来替代 dlv 命令。然后就可以正常使用了。
https://github.com/go-delve/delve/issues/1707
https://github.com/microsoft/vscode-go/issues/2610