30. 如何使用 GDB 调试 Go 程序?

Hi,大家好,我是明哥。

在自己学习 Golang 的这段时间里,我写了详细的学习笔记放在我的个人微信公众号 《Go编程时光》,对于 Go 语言,我也算是个初学者,因此写的东西应该会比较适合刚接触的同学,如果你也是刚学习 Go 语言,不防关注一下,一起学习,一起成长。

我的在线博客:http://golang.iswbm.com
我的 Github:github.com/iswbm/GolangCodingTime


做为新手,熟练掌握一个好的调试工具,对于我们学习语言或者排查问题的时候,非常有帮助。

你如果使用 VS Code 或者 Goland ,可以直接上手,我就不再写这方面的文章了。

其实相比有用户界面的 IDE 调试工具,我更喜欢简单直接的命令行调试,原因有三点:

  1. 速度快,个人感觉在 Windows 下速度巨慢
  2. 依赖少,在 Linux 服务器上 也能轻松调试
  3. 指令简单,我习惯只使用快捷键就能操作

如果你有和我一样的感受和习惯,可以看下今天的文章,介绍的是 GDB 调试工具。

1. 下载安装 Go

在 Linux 上进行调试,那咱所以得先安装 Go ,由于第一节里只讲了 Windows 的下载安装,并没有讲到在 Linux 上如何安装。所以这里要先讲一下,已经安装过了可以直接跳过。

首先在 go 下载页面上(https://golang.org/dl/),查看并复制源码包的的下载地址

登陆 linux 机器 ,使用 wget 下载

$ wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz

将下载的源码包解压到 /usr/local 目录下,并设置环境变量

[root@localhost ~]# tar -C /usr/local -xzf go1.14.2.linux-amd64.tar.gz
[root@localhost ~]# 
[root@localhost ~]# export PATH=$PATH:/usr/local/go/bin
[root@localhost ~]# which go
/usr/local/go/bin/go
[root@localhost ~]# 
[root@localhost ~]# go version
go version go1.14.2 linux/amd64
[root@localhost ~]# 

2. 开始进行调试

调试使用的是 GDB (好像要求版本 7.1 + ),使用前,请先确保你的机器上已经安装 GDB

[root@localhost code]# which gdb
/usr/bin/gdb

准备就绪后,先在目录下写一个测试文件

package main

import "fmt"

func main(){
  msg := "hello, world"
  fmt.Println(msg)
}

然后执行 如下命令进行编译,里面有好多个参数,有疑问的可以自行搜索引擎

# 关闭内联优化,方便调试
$ go build -gcflags "-N -l" demo.go

# 发布版本删除调试符号
go build -ldflags “-s -w”

最后使用 GDB 命令进入调试界面

# 如果你喜欢这种界面的话,用这条命令
$ gdb -tui demo

# 如果你跟我一样不喜欢不习惯用界面,就使用这个命令
$ gdb demo

完整操作如下:

进入 GDB 调试界面后,并不是立即可用,你先需要回车,然后再你敲入几行命令,调试窗口就会出现代码。

(gdb) b    main.main   # 在 main 包里的 main 函数 加断点
Breakpoint 1 at    0x4915c0: file /home/wangbm/code/demo.go, line 5.
(gdb) run  # 执行进程
Starting program: /home/wangbm/code/demo 
Breakpoint 1, main.main () at /home/wangbm/code/demo.go:5
(gdb) 

3. 详解调试指令

要熟练使用 GDB ,你得熟悉的掌握它的指令,这里列举一下

  • r:run,执行程序
  • n:next,下一步,不进入函数
  • s:step,下一步,会进入函数
  • b:breakponit,设置断点
  • l:list,查看源码
  • c:continue,继续执行到下一断点
  • bt:backtrace,查看当前调用栈
  • p:print,打印查看变量
  • q:quit,退出 GDB
  • whatis:查看对象类型
  • info breakpoints:查看所有的断点
  • info locals:查看局部变量
  • info args:查看函数的参数值及要返回的变量值
  • info frame:堆栈帧信息
  • info goroutines:查看 goroutines 信息。在使用前 ,需要注意先执行 source /usr/local/go/src/runtime/runtime-gdb.py
  • goroutine 1 bt:查看指定序号的 goroutine 调用堆栈
  • 回车:重复执行上一次操作

其中有几个指令的使用比较灵活

比如 l – list,查看代码

# 查看指定行数上下5行
(gdb) l 8

# 查看指定范围的行数
(gdb) l 5:8

# 查看指定文件的行数上下5行
l demo.go:8

# 可以查看函数,记得加包名
l main.main

把上面的 l 换成 b ,大多数也同样适用

# 在指定行打断点
(gdb) b 8


# 在指定指定文件的行打断点
b demo.go:8

# 在指定函数打断点,记得加包名
b main.main

还有 p – print,打印变量

# 查看变量
(gdb) p var

# 查看对象长度或容量
(gdb) p $len(var)
(gdb) p $cap(var)

# 查看对象的动态类型
(gdb) p $dtype(var)
(gdb) iface var

# 举例如下
(gdb) p i
$4 = {str = "cbb"}
(gdb) whatis i
type = regexp.input
(gdb) p $dtype(i)
$26 = (struct regexp.inputBytes *) 0xf8400b4930
(gdb) iface i
regexp.input: struct regexp.inputBytes *

以上就是关于 GDB 的使用方法,非常简单,可以自己手动敲下体验一下。

参考文章

系列导读

01. 开发环境的搭建(Goland & VS Code)

02. 学习五种变量创建的方法

03. 详解数据类型:整形与浮点型

04. 详解数据类型:byte、rune与string

05. 详解数据类型:数组与切片

06. 详解数据类型:字典与布尔类型

07. 详解数据类型:指针

08. 面向对象编程:结构体与继承

09. 一篇文章理解 Go 里的函数

10. Go语言流程控制:if-else 条件语句

11. Go语言流程控制:switch-case 选择语句

12. Go语言流程控制:for 循环语句

13. Go语言流程控制:goto 无条件跳转

14. Go语言流程控制:defer 延迟调用

15. 面向对象编程:接口与多态

16. 关键字:make 和 new 的区别?

17. 一篇文章理解 Go 里的语句块与作用域

18. 学习 Go 协程:goroutine

19. 学习 Go 协程:详解信道/通道

20. 几个信道死锁经典错误案例详解

21. 学习 Go 协程:WaitGroup

22. 学习 Go 协程:互斥锁和读写锁

23. Go 里的异常处理:panic 和 recover

24. 超详细解读 Go Modules 前世今生及入门使用

25. Go 语言中关于包导入必学的 8 个知识点

26. 如何开源自己写的模块给别人用?

27. 说说 Go 语言中的类型断言?

28. 这五点带你理解Go语言的select用法



发表评论

邮箱地址不会被公开。 必填项已用*标注