Delve 是 Go 语言的一个调试器。其目标是为 Go 语言提供一个易用,拥有完整功能的调试工具。
安装可以参考这里。
用 dlv version
命令验证是否安装成功:
$dlvversionDelveDebuggerVersion:1.7.1Build:$Id:3bde2354aafb5a4043fd59838842c4cd4a8b6f0b$
构建应用
在实际项目中 Delve 可以方便我们在本地调试部署在远程的 Go 应用,但为了使 Delve 的调试器正常工作,一些信息必须在构建过程中避免被编译器或链接器优化。这通过给 go build
添加参数来实现。
构建应用时禁用编译器优化
为了保证进行 debug 时实际运行的代码与源代码相同,需要使用下面的命令构建应用以禁止编译器在编译时对代码进行优化。
gobuild-gcflags="all=-N-l"-obin/app
go build 可以用 -gcflags
给 go 编译器传入参数,也就是传给 go tool compile
的参数,因此可以用 go tool compile --help
查看所有可用的参数。"all=-N -l"
表示对所有包的编译应用 -N 和 -l。
执行 go tool compile --help
可以看到 -N 和 -l 的作用:
-Ndisableoptimizations#禁用优化-ldisableinlining#禁用内联优化
使用 -m 可以查看编译器优化决策。
Delve 并不强制禁用编译器优化,但这可能会导致实际运行代码与源代码不匹配的情况,那这部分不匹配的代码(如被内联优化的代码)就没法对其进行 debug。而生产环境对性能是敏感的,优化策略不应该被轻易放弃。
确保链接器生成 DWARF 信息
另外,在构建 release 包时我们通常会加上 ldflags 参数:-ldflags '-w -s'
。ldflags 给链接器传递参数,-w
将可执行文件体积缩小近 20 %。
用 go tool link --help
查看 -w 和 -s 作用。
-sdisablesymboltable#不使用符号表-wdisableDWARFgeneration#不生成DWARF信息
需要注意的是,Delve 依赖于 DWARF 信息,因此如果想用 Delve 进行调试,就不能使用 -w 参数。
用 Delve 调试应用
Delve 提供了丰富的本地应用调试能力,此外,Delve 还允许我们从远程连接到其调试器,提供了在本地调试远程应用的能力。
直接运行应用
Delve 有两种方式直接运行应用。一种为在应用根目录(main.go 同级)下直接以 debug 模式启动应用,启动后会进入 Delve 的交互模式。
$dlvdebugType'help'forlistofcommands.(dlv)threads*Thread457777at:0(dlv)
输入 help 查看所有可用命令,输入 quit 退出并终止程序。
另一种为运行可执行文件:
$gobuild-odemo$dlvexecdemoType'help'forlistofcommands.(dlv)threads*Thread459012at:0(dlv)
附着到正在运行的 Go 进程上
构建并启动 web 服务。
$gobuild$./demo2021/09/0615:26:23readconfigfrom:config.yaml2021/09/0615:26:23startserverandlisten:127.0.0.1:8081
dlv 附着到 PID 为 17062 的 demo 应用上。
$psPIDTTYTIMECMD17062ttys0000:00.02./thewaytowire$dlvattach17062Type'help'forlistofcommands.(dlv)
将 Delve 调试器暴露,允许远程连接调试
上述方式都是在本地进行调试,其基本逻辑都是先启动应用,然后启动 Delve 的调试器,然后让调试器 attach 到应用进程上。
为了能够从远程操控 Delve 的调试器,需要将调试器暴露到网络中,指定远程连接的端口,从远程连接到调试器使用的 api 版本,以及其它参数。上述的三种方式:debug
, exec
, attach
都支持从远程操控,只需为 dlv 命令加上下述参数:
--listen=:2345--headless=true--api-version=2--accept-multiclient
最后一步,本地连接运行在远程的 Delve 调试器
Delve 支持多个编辑器,可以参考 这里。
下面为 GoLand 的使用方式。
创建配置。
连接调试器。