从零学习 Go 语言(30):如何使用 GDB 调试 Go 程序?

hello_wbm · · 750 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

![](http://image.iswbm.com/20200607145423.png) 在线博客:http://golang.iswbm.com/ Github:https://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/),查看并复制源码包的的下载地址 ![](http://image.iswbm.com/20200428180632.png) 登陆 linux 机器 ,使用 wget 下载 ```shell $ wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz ``` ![](http://image.iswbm.com/20200428180713.png) 将下载的源码包解压到 `/usr/local` 目录下,并设置环境变量 ```shell [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 ``` 准备就绪后,先在目录下写一个测试文件 ```go package main import "fmt" func main(){ msg := "hello, world" fmt.Println(msg) } ``` 然后执行 如下命令进行编译,里面有好多个参数,有疑问的可以自行搜索引擎 ```shell # 关闭内联优化,方便调试 $ go build -gcflags "-N -l" demo.go # 发布版本删除调试符号 go build -ldflags “-s -w” ``` 最后使用 GDB 命令进入调试界面 ```shell # 如果你喜欢这种界面的话,用这条命令 $ gdb -tui demo # 如果你跟我一样不喜欢不习惯用界面,就使用这个命令 $ gdb demo ``` 完整操作如下: ![](http://image.iswbm.com/20200428181902.png) 进入 GDB 调试界面后,并不是立即可用,你先需要回车,然后再你敲入几行命令,调试窗口就会出现代码。 ```shell (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) ``` ![](http://image.iswbm.com/20200428182620.png) ## 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 的使用方法,非常简单,可以自己手动敲下体验一下。 **参考文章** - [go 官方对于 gdb 的使用说明](https://golang.org/doc/gdb) - [Mac 调试 golang 程序]([https://www.do1618.com/archives/771/mac-gdb-%E8%B0%83%E8%AF%95-golang-%E7%A8%8B%E5%BA%8F/](https://www.do1618.com/archives/771/mac-gdb-调试-golang-程序/)) ## 系列导读 --- [从零学习 Go 语言(01):一文搞定开发环境的搭建](https://studygolang.com/articles/27365) [从零学习 Go 语言(02):学习五种变量创建的方法](https://studygolang.com/articles/27432) [从零学习 Go 语言(03):数据类型之整型与浮点型](https://studygolang.com/articles/27440) [从零学习 Go 语言(04):byte、rune与字符串](https://studygolang.com/articles/27463) [从零学习 Go 语言(05):数据类型之数组与切片](https://studygolang.com/articles/27508) [从零学习 Go 语言(06):数据类型之字典与布尔类型](https://studygolang.com/articles/27563) [从零学习 Go 语言(07):数据类型之指针](https://studygolang.com/articles/27585) [从零学习 Go 语言(08):流程控制之if-else](https://studygolang.com/articles/27613) [从零学习 Go 语言(09):流程控制之switch-case](https://studygolang.com/articles/27660) [从零学习 Go 语言(10):流程控制之for 循环](https://studygolang.com/articles/28120) [从零学习 Go 语言(11):goto 无条件跳转](https://studygolang.com/articles/28472) [从零学习 Go 语言(12):流程控制之defer 延迟语句](https://studygolang.com/articles/28515) [从零学习 Go 语言(13):异常机制 panic 和 recover](https://studygolang.com/articles/28519) [从零学习 Go 语言(14):Go 语言中的类型断言是什么?](https://studygolang.com/articles/29305) [从零学习 Go 语言(15):学习 Go 语言的结构体与继承](https://studygolang.com/articles/29306) [从零学习 Go 语言(17):Go 语言中的 make 和 new 有什么区别?](https://studygolang.com/articles/29315) [从零学习 Go 语言(18):Go 语言中的 语句块与作用域](https://studygolang.com/articles/29365) [从零学习 Go 语言(19):Go Modules 前世今生及入门使用](https://studygolang.com/articles/29371) [从零学习 Go 语言(20):关于包导入必学的 8 个知识点](https://studygolang.com/articles/29404) [从零学习 Go 语言(21):一文了解 Go语言中编码规范](https://studygolang.com/articles/29477) [从零学习 Go 语言(22):Go 语言中如何开源自己写的包给别人用?](https://studygolang.com/articles/29609) [从零学习 Go 语言(23):一篇文章搞懂 Go 语言的函数](https://studygolang.com/articles/29628) [从零学习 Go 语言(24):理解 Go 语言中的 goroutine](https://studygolang.com/articles/29641) [从零学习 Go 语言(25):详解信道/通道](https://studygolang.com/articles/29704) [从零学习 Go 语言(26):通道死锁经典错误案例详解](https://studygolang.com/articles/29756) [从零学习 Go 语言(27):学习 Go 协程中的 WaitGroup](https://studygolang.com/articles/29783) [从零学习 Go 语言(28):学习 Go 协程中的互斥锁和读写锁](https://studygolang.com/articles/29838) [从零学习 Go 语言(29):Go 语言中的 select 用法](https://studygolang.com/articles/29852) --- ![](http://image.python-online.cn/20200321153457.png)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

750 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传