本文转载自微信公众号「洋芋编程」,作者蛮荆 。转载本文请联系洋芋编程公众号。
Delve 用来调试 Go 语言开发的程序,该工具的目标是为 Go 语言提供一个简单、功能齐全的调试工具。
$ go install github.com/go-delve/delve/cmd/dlv@latest
# 安装完成后查看版本
$ dlv verison
Delve Debugger
Version: 1.20.1
Build: $Id: 96e65b6c615845d42e0e31d903f6475b0e4ece6e
我们首先从一个简单的示例程序开始,改程序打印字符串 hello world, 然后结束并退出。
// main.go
package main
func main() {
println("hello world")
}
$ dlv debug main.go
# Type 'help' for list of commands.
(dlv)
# 输入 help 查看参数说明
(dlv) help
The following commands are available:
Running the program:
call ------------------------ Resumes process
...
...
types ---------------------- Print list of types
Type help followed by a command for full documentation.
# 运行程序
(dlv) continue
hello world
Process 3637 has exited with status 0
# 编译源文件
$ go build -o main main.go
$ dlv exec ./main
Type 'help' for list of commands.
(dlv)
# 接下来的步骤和调试源文件的一样,这里不再赘述
为了让进程保持在运行状态,我们在程序中加一行休眠代码:
package main
import "time"
func main() {
time.Sleep(time.Minute)
println("hello world")
}
调试前先运行程序:
$ go run main.go
# 查看进程 ID
$ ps -ef | grep "go run main.go"
7602 27666 0 21:30 pts/6 00:00:00 go run main.go
# 调试进程
$ dlv attach 7602
Type 'help' for list of commands.
(dlv)
...
# 1 分钟之后,main.go 并未正常退出,因为当前正在调试
# 输入 continue 继续运行
(dlv) continue
Process 7602 has exited with status 0
下列命令是启动 dlv 调试后可用的命令 (也就是当前命令行变为 (dlv) 之后可用)。
命令 |
描述 |
call |
恢复进程,调用函数 (实验阶段) |
continue |
继续运行程序,直到遇到断点或程序结束 |
next |
单步调试 |
restart |
重新运行 |
step |
单步调试某个函数 |
step-instruction |
单步调试某个 CPU 指令 |
stepout |
从当前函数跳出 |
命令 |
描述 |
break |
设置断点 |
breakpoints |
打印所有断点 |
clear |
删除断点 |
clearall |
删除所有断点 |
condition |
设置条件断点 |
on |
设置一个断点触发时执行的命令 |
toggle |
打开/关闭 断点 |
命令 |
描述 |
args |
打印函数参数 |
display |
每次程序停止时打印表达式的值 |
examinemem |
解析给定地址的内存 |
locals |
打印本地变量 |
|
解析一个表达式 |
regs |
打印寄存器信息 |
set |
设置变量的值 |
vars |
打印包内变量 |
whatis |
打印类型信息 |
命令 |
描述 |
goroutine |
打印或切换 goroutine |
goroutines |
打印所有 goroutine |
thread |
切换到指定的线程 |
threads |
打印所有线程信息 |
命令 |
描述 |
deferred |
在 defer 上下文中执行命令 |
frame |
设置当前帧,或在不同的帧上执行命令 |
stack |
打印堆栈信息 |
命令 |
描述 |
config |
更改配置参数 |
disassemble |
反汇编 |
dump |
dump core |
exit |
结束调试,也可以用 |
最后,我们使用一个的小例子,熟悉下常用的几个命令。
示例程序代码如下:
// main.go
package main
var (
x = 1024
)
func main() {
for i := 0; i < 5; i++ {
println(i)
}
}
# 开始调试
$ dlv debug main.go
Type 'help' for list of commands.
(dlv)
# 增加断点
(dlv) b main.main
Breakpoint 1 set at 0x45f0c6 for main.main() ./main.go:7
# 查看断点
(dlv) bp
...
Breakpoint 2 (enabled) at 0x45f0c6 for main.main() ./main.go:7 (0)
# 运行程序
(dlv) continue
> main.main() ./main.go:7 (hits goroutine(1):1 total:1) (PC: 0x45f0c6)
2:
3: var (
4: x = 1024
5: )
6:
=> 7: func main() {
8: for i := 0; i < 5; i++ {
9: println(i)
10: }
11: }
12:
# 可以看到,程序停在了设置的断点上
# 打印包变量
(dlv) vars vars main.x
...
main.x = 1024
...
# 单步调试
(dlv) next
> main.main() ./main.go:8 (PC: 0x45f0d4)
3: var (
4: x = 1024
5: )
6:
7: func main() {
=> 8: x = 0
9: for i := 0; i < 5; i++ {
10: println(i)
11: }
12: }
13:
# 再次单步调试
(dlv) next
> main.main() ./main.go:9 (PC: 0x45f0df)
4: x = 1024
5: )
6:
7: func main() {
8: x = 0
=> 9: for i := 0; i < 5; i++ {
10: println(i)
11: }
12: }
13:
14: //timeout := time.After(time.Minute)
# 可以看到,程序停在了循环语句
# 打印包变量
(dlv) vars main.x
main.x = 0
# 再次单步调试
(dlv) next
> main.main() ./main.go:10 (PC: 0x45f0f4)
5: )
6:
7: func main() {
8: x = 0
9: for i := 0; i < 5; i++ {
=> 10: println(i)
11: }
12: }
13:
14: //timeout := time.After(time.Minute)
15: //
# 打印本地变量
(dlv) locals
i = 0
# 查看堆栈信息
(dlv) stack
0 0x000000000045f0f4 in main.main
at ./main.go:10
1 0x00000000004358b8 in runtime.main
at /usr/local/go/src/runtime/proc.go:250
2 0x000000000045c0c1 in runtime.goexit
at /usr/local/go/src/runtime/asm_amd64.s:1594
# 打印 goroutine 信息
(dlv) goroutine
Thread 27873 at ./main.go:10
Goroutine 1:
...
# 删除所有断点
(dlv) clearall
Breakpoint 1 cleared at 0x45f0c6 for main.main() ./main.go:7
# 继续执行
(dlv) continue
1
2
3
4
Process 27873 has exited with status 0
# 退出调试
(dlv) exit
Delve 支持以插件的形式集成到主流的 IDE 里面,具体的支持列表请看 这个页面[1]。
一般是被编译器优化了,比如内联会导致 dlv 单步调试无法打印某些变量,解决方法是禁止编译优化。
# 禁用内联和优化 (细节可以阅读引用文章列表)
go run -gcflags "-N -l" main.go
[1] 这个页面: https://github.com/go-delve/delve/blob/master/Documentation/EditorIntegration.md
[2] go-delve/delve: https://github.com/go-delve/delve
[3] 如何定位 golang 进程 hang 死的 bug: https://xargin.com/how-to-locate-for-block-in-golang/
[4] Debugging with GDB: https://sourceware.org/gdb/current/onlinedocs/gdb.html/
[5] 100-gdb-tips: https://github.com/hellogcc/100-gdb-tips
[6] 深入 Go 语言 - 11: https://colobu.com/2016/07/04/dive-into-go-11/
[7] WSL2 安装 perf: https://gist.github.com/abel0b/b1881e41b9e1c4b16d84e5e083c38a13
网页名称:Go调试工具-Delve快速入门
网站地址:http://www.shufengxianlan.com/qtweb/news35/475335.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联