Golang代码调试器delve,必先利其器

上篇文章使用gdb作为调试器,本文介绍使用delve代码调试器,记录学习笔记。

安装

要求go1.5及以上版本

brew安装

1
brew install go-delve/delve/delve

源码编译

创建证书步骤参看《用Golang代码调试器gdb, 了解interface的存储结构》,这里不再赘述。

下载源码

1
git clone https://github.com/derekparker/delve.git && cd delve

编译安装

1
CERT=dlv-cert make install

dlv-cert是创建的证书名

调试

delve命令和gdb比较类似,先看下delve的命令

1
dlv -h

Alt text

以相同的代码作为示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

type Ner interface {
a()
b(int)
c(string) string
}

type N int

func (N) a() {
}

func (*N) b(int) {
}

func (*N) c(string) string {
return ""
}

func main() {
var n N
var ner Ner = &n

ner.a()
}

编译Go程序的时候无需注意以下两点

  1. 传递参数-ldflags “-s”,忽略debug的打印信息
  2. 传递-gcflags “-N -l” 参数,这样可以忽略Go内部做的一些优化,聚合变量和函数等优化,这样对于GDB调试来说非常困难,所以在编译的时候加入这两个参数避免这些优化。

编译示例代码go build main.go,目录下生成main可执行文件

dlv exec ./main调试代码或者dlv debug main.go(debug会自己完成编译)
Alt text

调试代码
Alt text

高级用法

delve支持调试已经运行的golang程序。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"fmt"
"sync"
"time"
)

func dostuff(wg *sync.WaitGroup, i int) {
fmt.Printf("goroutine id %d\n", i)
time.Sleep(20 * 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 < workers; i++ {
go dostuff(&wg, i)
}
wg.Wait()
}

代码创建了10个gorouting,main等待所有gorouting执行完成后退出。

先编译示例代码go build main.go

启动./main进程,查看进程pid
Alt text

delve attach 调试进程,设置断点
Alt text

delve还支持远程调试哦,使用dlv connect ip:port。好了,今天就写到这里了。

总体来说delve比gdb更适合于调试golang。