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

参考

https://github.com/derekparker/delve/blob/master/Documentation/cli/getting_started.md#debugging-main-packages