2019独角兽企业重金招聘Python工程师标准>>>
代码错误追踪是一件很头痛的事,使用delve debug工具可以轻松完成对go程序的调试。
安装
此处介绍Linux上的安装,其他的大同小异,
第一种方式是用go get获取。
go get -u github.com/derekparker/delve/cmd/dlv
第二种是使用源码安装:
$ git clone https://github.com/derekparker/delve.git $GOPATH/src/github.com/derekparker/delve
$ cd $GOPATH/src/github.com/derekparker/delve
$ make install
但是必须确认设置了GOPATH环境变量,
还要注意的事:如果您使用的是GO 1.5,则必须在继续之前设置GO15VANDORAMED=1
安装中的问题:
1. 环境变量GOARCH
github.com\derekparker\delve\proc\disasm.go:9: undefined: ArchInst
这个问题就是因为没有设置go的环境变量GOARCH为操作系统或者go安装时的位数( 386 / amd64 ),根据自己环境设置。
2. Linux( Ubuntu) 不允许不同用户attach ID连接程序进行调试
Could not attach to process. If your uid matches the uid of the target process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf
将此文件下的kernel.yama.ptrace_scope = 1 改为0, 允许普通用户调试。但必须重启生效。
调试代码
示例代码:
package main
import(
"fmt"
"sync"
"time"
)
func dostuff(wg *sync.WaitGroup , i int){
fmt.Printf("groutime id %d \n", i)
time.Sleep(300*time.Second)
fmt.Printf("goroutine id %d\n", i)
wg.Done()
}
func main(){
var wg sync.WaitGroup
workers := 10
wg.Add(workers)
for i:=0; i
程序中启用了10个goroutine来分别往控制台输出, 下面使用delve来调试程序:
dlv debug delve.go
运行这个命令,dlv会去编译你的代码,然后传一些参数给编译器,好让编译器编译出来更加方便调试的可执行文件,然后启动了你的程序,并且attach
上去,这样你的console就会停留在了debug session
,下面就可以调试程序了。
那么,我们先在main函数上设置一个断点。
(dlv) break main.main
Breakpoint 1 set at 0x22d3 for main.main() ./test-debug.go:16
输出信息里面告诉了我们断点的 ID和断点的位置,函数名和文件名以及所在行数。我们使用continue
命令让程序运行到我们打断点的地方。
(dlv) continue
> main.main() ./test-debug.go:16 (hits goroutine(1):1 total:1) (PC: 0x22d3)
11: time.Sleep(300 * time.Second)
12: fmt.Printf("goroutine id %d\n", i)
13: wg.Done()
14: }
15:
=> 16: func main() {
17: var wg sync.WaitGroup
18: workers := 10
19:
20: wg.Add(workers)
21: for i := 0; i < workers; i++ {
(dlv)
现在程序就停在了第一个断点,现在我们可以使用next
命令让程序运行到下一句话,如果你想继续向下,可以直接按回车(如果你按下回车键,Delve会重复上一条命令)。
(dlv) next
> main.main() ./test-debug.go:17 (PC: 0x22d7)
12: fmt.Printf("goroutine id %d\n", i)
13: wg.Done()
14: }
15:
16: func main() {
=> 17: var wg sync.WaitGroup
18: workers := 10
19:
20: wg.Add(workers)
21: for i := 0; i < workers; i++ {
22: go dostuff(&wg, i)
(dlv)
> main.main() ./test-debug.go:18 (PC: 0x22f1)
13: wg.Done()
14: }
15:
16: func main() {
17: var wg sync.WaitGroup
=> 18: workers := 10
19:
20: wg.Add(workers)
21: for i := 0; i < workers; i++ {
22: go dostuff(&wg, i)
23: }
(dlv)
> main.main() ./test-debug.go:20 (PC: 0x22fa)
15:
16: func main() {
17: var wg sync.WaitGroup
18: workers := 10
19:
=> 20: wg.Add(workers)
21: for i := 0; i < workers; i++ {
22: go dostuff(&wg, i)
23: }
24: wg.Wait()
25: }
(dlv)
现在我们可以尝试使用print
命令去看一下变量的值。
(dlv) print wg
sync.WaitGroup {
state1: [12]uint8 [0,0,0,0,0,0,0,0,0,0,0,0],
sema: 0,}
(dlv) print workers
10
(dlv)
同时你也可以输出一个表达式
(dlv) print workers < 100
true
简洁的命令
1. 指定行号设置断点:
(dlv) b main.go:16 #在 main.go 的第 16 行设置断点。
2. 查看所有断点
(dlv) bp #查看当前所有断点
3. 运行至下一个断点
(dlv) c #运行到下一个断点或者到程序结尾
4. 打印变量
(dlv) p a #打印变量 a 的值 ( 此变量必须是程序中声明的)
5. 单步执行代码
(dlv) n #单步执行代码
6. 手动修改变量值
(dlv) set a=1 #设置变量a 的值(变量在程序中存在)
命令大全
命令 | 描述 |
---|---|
args | 打印函数参数 |
break | 设置一个断点 |
breakpoints | 打印激活的断点信息 |
clear | 删除断点 |
clearall | 删除所有的断点 |
condition | 设置断点条件 |
continue | 运行到断点或程序终止 |
disassemble | 拆解器 |
exit | 退出debugger |
frame | 在不同的框架上执行的命令 |
funcs | 打印函数列表 |
goroutine | 显示或更改当前goroutine |
goroutines | 列出程序的全部goroutines |
help | 打印出帮助信息 |
list | 显示源代码 |
locals | 打印局部变量 |
next | 跳到下一行 |
on | 在遇到断点时执行一个命令 |
评估表达式 | |
regs | 打印CPU寄存器的内容 |
restart | 重启进程 |
set | 更改变量的值 |
source | 执行包含delve命令列表的文件 |
sources | 打印源文件列表 |
stack | 打印堆栈跟踪 |
step | 单步执行程序 |
step-instruction | 单步单个执行cpu指令 |
thread | 切换到指定的线程 |
threads | 打印每一个跟踪线程的信息 |
trace | 设置跟踪点 |
types | 打印类型列表 |
vars | 打印某个包内的(全局)变量 |
Delve 命令详解
我们在命令行中输入dlv, 会看到:
Delve is a source level debugger for Go programs.
Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.
The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.
Pass flags to the program you are debugging using `--`, for example:
`dlv exec ./hello -- server --config conf/config.toml`
使用方式
Usage:
dlv [command]
可用的命令
Available Commands:
attach 关联到一个已经运行的程序上进行调试.
dlv attach [程序的PID]
connect Connect to a headless debug server.
core Examine a core dump.
debug Compile and begin debugging main package in current directory, or the package specified.
exec Execute a precompiled binary, and begin a debug session.
help Help about any command
run Deprecated command. Use 'debug' instead.
test Compile test binary and begin debugging program.
trace Compile and begin tracing program.
version Prints version.
为调试附加的参数
Flags:
--accept-multiclient Allows a headless server to accept multiple client connections. Note that the server API is not reentrant and clients will have to coordinate.
--api-version int Selects API version when headless. (default 1)
--backend string Backend selection:
部分为列出...
未完待续.....