这个文档总结了,我自己在linux通过delve上调试go代码的一些操作,比较常用的。无论是在调试应用,还是自己trace源码都挺好用。
GO version: 1.16.8
dlv versoin:1.7.2
dlv安装
go版本小于1.16的用下面方式安装
dlv指令
仅列出常用或者会用到的
指令 | 用处 | 实操 |
---|---|---|
attach | 这个命令将使Delve控制一个已经运行的进程,并开始一个新的调试会话。 当退出调试会话时,你可以选择让该进程继续运行或杀死它。 | case1 |
exec | 这个命令将使Delve执行二进制文件,并立即附加到它,开始一个新的调试会话。请注意,如果二进制文件在编译时没有关闭优化功能,可能很难正确地调试它。请考虑在Go 1.10或更高版本上用-gcflags="all=-N -l "编译调试二进制文件,在Go的早期版本上用-gcflags="-N -l"。 | case2 |
help | 使用手册 | case3 |
debug | 默认情况下,没有参数,Delve将编译当前目录下的 "main "包,并开始调试。或者,你可以指定一个包的名字,Delve将编译该包,并开始一个新的调试会话。 | case4 |
test | test命令允许你在单元测试的背景下开始一个新的调试会话。默认情况下,Delve将调试当前目录下的测试。另外,你可以指定一个包的名称,Delve将在该包中调试测试。双破折号`--`可以用来传递参数给测试程序。 | case5 |
version | 查看dlv版本 | case6 |
dlv调试指令
仅记录个人觉得会用到的指令
断点管理
指令 | 缩写 | 用法 | 案例 |
---|---|---|---|
break | b | 设置断点 | case7 |
breakpoints | bp | 查看当前所有断点 | case8 |
clear | / | 删除断点 | case9 |
clearall | / | 删除多个断点 | case10 |
toggle | / | 启用或关闭断点 | case11 |
程序执行中的调试指令
指令 | 缩写 | 用法 | 案例 |
---|---|---|---|
continue | c | 继续执行到一个断点或者程序结束吗 | case12 |
next | n | 执行下一行代码 | case13 |
restart | r | 重新执行程序 | case14 |
step | s | 执行代码的下一步 | case15 |
step-instruction | si | 执行下一行机器码 | case16 |
stepout | so | 跳出当前执行函数 | case17 |
参数管理
指令 | 缩写 | 用法 | 案例 |
---|---|---|---|
args | / | 打印函数input | case18 |
display | / | 打印加入到display的变量的值,每次执行下一行代码或下一个断点时 | case19 |
locals | / | 打印局部变量 | case20 |
p | 打印表达式的结果 | case21 | |
set | / | 设置某个变量的值 | case22 |
vars | / | 查看全局变量 | case23 |
whatis | / | 查看变量类型 | case24 |
其他
指令 | 缩写 | 用法 | 案例 |
---|---|---|---|
disassemble | disass | 查看反编译后的代码,机器码 | case25 |
exit | quit / q | 退出 | case26 |
funcs | / | 打印程序用到的所有函数 | case27 |
help | h | 帮助信息 | case28 |
list | ls / l | 打印代码 | case29 |
dlv实操案例
测试代码
case1 attach
我理解的就是对一个阻塞的程序进行debug,比如http server。
dlv attach 176
case2 exec
对一个可执行文件进行调试,是针对编译后的。
go build -v
sgo build -gcflags "-N -l" -v
case3 help
就是单纯的帮助信息
case4 debug
debug会从一个包的main.go开始调试,所以这个包必须在gopath下,不然会报找不到package
case5 test
调试单元测试,单元测试会编译整个包,所以test后面跟的是项目根目录的名称
case6 version
查看版本
case7 break
设置断点,设置断点的方法一般就是
b main.randHandlerb main.go:24
case8 breakpoints
打印当前所有断点。1,2,3是断点id,后面跟着的是状态。这个状态通过后面的toggle来操作。
case9 clear
删除某个断点,删除断点一般用的就是id来删除
case10 clearall
删除多个断点,如果没有跟上参数,就是全部删除
case11 toggle
对断点的启禁用,启用是enable,禁用是disabled。禁用状态下的断定,不会执行断点该有的功能。
case12 continue
continue一般是执行到下一个断点的地方,如果没有设置断点,那就直接执行程序完成,通常用的是缩写c。
cc
case13 next
next是执行到一行代码,一行代码即使是函数,也会直接执行过去,不会跳到函数里面。如下图,从17执行到18行
case14 restart
restart就是重头开始执行,但是断点会保留。所以即使重新执行,有打断点的地方,也会停止在打断点的地方。注意,这个restart只能用在delve自己创建的进程,比如上面的attach,就不能restart。
case15 step
step也是执行一行代码,和next不同的是,如果是函数调用,就会进到函数里面
case16 step-instruction
si
case17 stepout
s进一个函数之后,发现不是想要trace的函数,可以通过stepout,直接跳出函数
case18 args
打印当前函数的输入参数的值,这个在调试函数的时候很重要
case19 display
display就是相当于把你想要监控的变量,在每执行一行的时候都打印出来。
case20 locals
打印当前函数的局部变量,这个在调试函数的初始值的时候非常方便。
case21 print
print可以来打印某些变量,或者某些表达式,这样可以做一些简单的测试
case22 set
set可以设置某个变量的值,这个在调试边界条件,或者出现bug,想要继续调下去的时候非常有用
case23 vars
vars是打印全局变量,这个程序里面的,所以也包含一些runtime里面的。如果是自己的全局变量,最好带上名称,或者用正则表达式过滤。
case24 whatis
whatis是打印某个变量的类型
case25 disassemble
反编译,在case16里面有用到。反编译这个指令一般我是在trace源码的时候才会用到的,想看下源码里面到底是怎么执行的。或者是go底层一些逻辑是汇编写的,才会去用这个反编译。反编译里面踩过的一个坑,可以见:
case26 exit
退出,不用说了
case27 funcs
和vars一样,也是整个程序的,查看所有的方法。要想找到自己的方法,最好加上包名,或者通过正则表达式。
case28 help
查看任何一个指令的使用方式,说明。
case29 list
查看代码,因为有时候比如在反编译,或者执行什么表达式了,忘了代码执行到哪里了,可以用一下list。
有其他用到的觉得好用的指令,也可以多多交流呀。