原创分享 go runtime debug 小技巧

go-coder · 2020年09月20日 · 1690 次阅读
本帖已被设为精华帖!

来自公众号:新世界杂货铺

前言

本意是打算研究一下 go 程序的启动流程,然后就去网上搜索了一下入门教程。结果令我有点沮丧,搜到的几乎所有文章开篇都是通过GDB调试, 然后就是不同平台下的汇编代码。。。

这令我很不开心, 虽然 C/C++ 应用很广泛, 但是我对它真的没啥兴趣啊, 对它相关的调试工具就更加不感冒了, 虽然它可以调试 go 程序, 但是总感觉心里少了点什么, 难道dlv它不香嘛, 于是就有了今天这篇文章

dlv 命令行 debug

dlv 的名头应该不用我多说, 所以我们直奔主题

  1. 开始 debug
dlv debug test.go

执行上述命令后, 就会进入 debug 交互命令行界面, 在这个界面任何时候输入h都会打印帮助信息.

  1. 增加函数断点
# 交互界面输入下面命令后, 会在main包下的main函数打上一个断点
b main.main
  1. 指定行断点
# 在test.go的文件第6行打上一个断点
b test.go:6
  1. 开始执行

如上图所示, 我们继续执行时会发现=>会停留在我们前面标记的断点处。这里的其他命令我们在本篇文章不做过多的介绍了, 我们尽量紧扣本篇的主题。

  1. 打印调用栈

如上图所示, 我们通过 dlv 的调用栈可以看见调用 main 函数之前,还执行了 asm_amd64.s(本次 debug 的机器为 mac) 的汇编代码和 proc.go 的 main 函数。

意外之喜, 本来只是单纯的不想用 GDB 调试去了解 go 程序的启动流程, 现在却也有了一些头绪, 下面我们继续本篇的主题

  1. 在 runtime 包中标记断点并开始调试

综上: 按照上面的步骤, 我们通过 dlv 就可以进行 runtiime 的调试, 并且还可以了解 go 程序的启动流程

vscode 图形化 debug

我个人比较喜欢用 vscode 进行代码编辑, 所以在撸 go 的时候用的也是 vscode, 体验还是非常不错的

关于 vscode 如何配置 go 的开发环境和配置图形化 debug 就不再本篇过多赘述, 笔者在这里分享一下自己在 vscode 中关于 go 的配置

"go.useLanguageServer": true,
"go.languageServerExperimentalFeatures": {
    "format": true,
    "diagnostics": true,
    "documentLink": true
},
"go.languageServerFlags": ["-rpc.trace"],
"go.gotoSymbol.includeGoroot": true,
"go.gotoSymbol.includeImports": true,
"go.useCodeSnippetsOnFunctionSuggestWithoutType": true,
"go.useCodeSnippetsOnFunctionSuggest": true,
"go.autocompleteUnimportedPackages": true,
  1. 打断点

本部分在备用电脑上面完成,go 版本为: go1.14.2

此次直接复用了前面文章go 中字符串转字节切片的容量的 demo。三个断点分别位于,main/test.go, runtime/proc.go 和 runtime/string.go.

  1. 运行

vscode 通过 F5 快捷键即可快速开始 debug

接下来, 你就可以开始快乐的 debug 之旅啦

debug 不出现在 call stack 的函数

细心的同学肯定已经发现了,在上面 vscode 图形化 debug 的调用栈里面并没有 runtime/string.go 的影子。接下来, 我们结合本篇的主题继续往下分析

相信看过我切片真的是引用嘛?这篇文章的同学,心里已经基本有数了。对于这种即没有调用栈也没有明确调用者的函数,我们遵循以下两点即可完成对它的 debug

  1. 首先查看其汇编代码
# go代码转汇编
go tool compile -N -l -S test.go

关键汇编代码如下:

如上图所示,我们发现了stringtoslicebyte函数, 这样我们就可以打断点了, 只要打上了断点就可以快乐的调试了

  1. runtime 函数打断点时机

部分 rumtime 函数打好断点后, debug 程序会无法启动, 这个时候就需要延迟打点 (“延迟打点” 为笔者自己总结的名字) 了。

首先,在 main 函数的入口处打一个断点(调用 runtime 函数之前的断点均可),删除 runtime 函数的断点。

最后, 等待 debug 程序启动了,再给 runtime 函数打上断点即可。

至此, 祝各位开启快乐的 debug 之旅。

注: 写本文时, 笔者所用 go 版本为: go1.13.4;

生命不息, 探索不止, 后续将持续更新有关于 go 的技术探索

原创不易, 卑微求关注收藏二连.

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
DennisMao GoCN 每日新闻 (2020-09-20) 中提及了此贴 09月20日 19:21
kevin 将本帖设为了精华贴 09月21日 09:55
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册