go程序调试
调试程序是程序猿的一项必备技能,有多种手段来调试程序,如打印控制台输出,查看日志,以及设置断点,使用debug做单步跟踪进去调试。这篇文章主要从go使用debug为题进行展开。
GDB
介绍
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。 在mac上安装,会有认证方面的问题,查了一些资料,没能解决,就放弃了。使用vagrant搭建了一个go的环境并安装了gdb工具,在需要使用gdb时,通常是将代码通过vagrant目录映射到linux虚拟主机中,然后进行GDB调试。这种用的也不是很多,一般主要使用GDB提供的x命令,查看下内存的值。
debug目标
- 设置断点
- 查看变量值的输出
- 查看变量内存地址
- 查看变量内存值
- 修改变量的值
基于以上四点,我们通过程序来展示gdb的基本用法
gdb用法
示例程序:
package main import ( "fmt" "os" ) func main() { fmt.Println("go debug.....") // 命令参数使用 var argc = len(os.Args) var argv = append([]string{}, os.Args...) fmt.Printf("argc:%d\n", argc) fmt.Printf("argv:%v\n", argv) // 查看变量内存地址及值 var aa = 1 var bb = -1 fmt.Println(aa) fmt.Println(bb) }
- 编译程序
go build -gcflags="-N -l" demo.go // -N -l用于关闭编译器的内联优化
- 启动gdb
gdb demo
- 设置断点break
(gdb) b main.main Breakpoint 1 at 0x488e60: file /home/vagrant/godemo/demo01/demo.go, line 8. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000488e60 in main.main at /home/vagrant/godemo/demo01/demo.go:8 (gdb)
启动程序run
(gdb) run arg1 agr2 Starting program: /home/vagrant/godemo/demo01/demo arg1 agr2 [New LWP 5976] [New LWP 5977] [New LWP 5978] Thread 1 "demo" hit Breakpoint 1, main.main () at /home/vagrant/godemo/demo01/demo.go:8 8 func main() { (gdb)
查看代码
(gdb) l 4 "fmt" 5 "os" 6 ) 7 8 func main() { 9 fmt.Println("go debug.....") 10 // 命令参数使用 11 var argc = len(os.Args) 12 var argv = append([]string{}, os.Args...) 13 fmt.Printf("argc:%d\n", argc) (gdb) 14 fmt.Printf("argv:%v\n", argv) 15 16 // 查看变量内存地址及值 17 var aa = 1 18 var bb = -1 19 20 fmt.Println(aa) 21 fmt.Println(bb) 22 } (gdb)
单步执行next
(gdb) n go debug..... 11 var argc = len(os.Args) (gdb) n 12 var argv = append([]string{}, os.Args...) (gdb) n 13 fmt.Printf("argc:%d\n", argc) (gdb) n argc:3 14 fmt.Printf("argv:%v\n", argv) (gdb) n argv:[/home/vagrant/godemo/demo01/demo arg1 agr2]
打印命令p
打印格式
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
17 var aa = 1 (gdb) n 18 var bb = -1 (gdb) p aa $1 = 1 (gdb) p &aa $2 = (int *) 0xc00007ce40 (gdb) p/x aa $3 = 0x1
查看内存值命令x
x/<n/f/u> <addr>
n、f、u是可选的参数。
n 是一个正整数,表示显示内存的长度
f 表示显示的格式,参见上面
u 表示字节数,GDB默认是4个bytes。
b表示单字节
h表示双字节
w表示四字节
g表示八字节
<addr>表示一个内存地址
(gdb) p &aa $2 = (int *) 0xc00007ce40 (gdb) x/1dg 0xc00007ce40 0xc00007ce40: 1 (gdb)
设置值命令
(gdb) set aa = 2 (gdb) p aa $4 = 2 (gdb)
程序调用栈bt
显示goroutines
info goroutines // 显示当前执行的goroutine列表,如下代码所示,带*的表示当前执行的
查看变量类型
whatis
这里只列出出来了一些基本的用法,gdb很强大,还有很多命令,可以深入程序执行的底层,通过以上几个命令,可以完成一个程序的基本调试。
delve
delve是专为go语言打造的debug工具,现在的一些IDE工具的debug功能就是基于这个实现的。
启动debug服务
dlv debug demo.go
其它的命令同gdb大体相同,初级的调试,高级的使用功能,还未深入研究,另外它还可以attach到一个运行的程序进行debug。
IDE工具
如果不习惯使用命令行,可以使用集成开发工具goland,这个带有图形化界面操作的debug工具,操作起来比较方便。
喜欢请关注“云端漫记", 持续为你更新