-
Notifications
You must be signed in to change notification settings - Fork 22
在VS Code上调试golang项目
在开始之前,请先确保你的go版本不低于1.20
为了方便演示,我们使用ozline/grpc-todolist这个项目,这个项目有一个experimental的实验性模块
请先打开vscode,并且载入项目的工作文件夹
Delve是专门针对go语言的调试器
go get -u github.com/go-delve/delve/cmd/dlv- 我们打开vscode的命令窗口(默认快捷键是
Ctrl/Command + Shift + P - 输入
Debug: Add Configuration,可以看见一个中文名为添加配置的选项,选择那个选项 - 选择调试器,选择
Go - 会再跳出来一个
Choose debug configuration,选择第一个Go: Launch Package即可
接下来,你就会在根目录的.vscode/launch.json中看到下面这些内容
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}"
}
]
}事实上,你也可以直接在根目录创建.vscode文件夹(注意是有点号的),然后在里面创建launch.json文件即可
这里先拿grpc-todolist中的调试配置作为例子
{
"version": "0.2.0",
"configurations": [
{
"name": "exp-client",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${file}",
"args": [
"-config",
"../../../config"
],
"env": {
"GRPC_GO_LOG_VERBOSITY_LEVEL": "99",
"GRPC_GO_LOG_SEVERITY_LEVEL": "info",
}
},
{
"name": "exp-server",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"args": [
"-config=../../config",
"-srvnum=0",
],
"env": {
"GRPC_GO_LOG_VERBOSITY_LEVEL": "99",
"GRPC_GO_LOG_SEVERITY_LEVEL": "info",
}
},
]
}这里只列举一些关键的,其余的可以忽略
| 属性 | 介绍 |
|---|---|
| name | 这个调试项的名称 |
| type | vscode利用这个type判断该用什么来调试 |
| mode | 调试模式,除了上面的auto,还可以填写debug/remote等,一般auto
|
| program |
${file} 代表调试当前文件,${fileDirname}表示调试当前文件夹 |
| args | 调试时给程序传递的参数 |
| env | 调试时的环境变量 |
更多的属性及内容,可以参考文末的Reference
如果完成了上述内容,就可以开始进行调试了
我们先把目光放到./cmd/experimental/client中,这是一个为实验性模块随便写的一个简易的grpc客户端
我们先启动grpc的服务端
make env-up # 启动项目环境
make experimental node=0 # 启动实验性模块的0号节点因为实验性模块之前还用于测试负载均衡,所以通常都会带上node=x的参数,当然,你也可以不带,默认参数就是0
回到vscode,打开./cmd/experimental/client/main.go,具体可以参考下面这个图(由于分辨率过高,看不清的话可以右键在新页面中查看图片)
关注到里面的设置断点,我们设置好一个断点后,左侧的调试栏底下的断点就会多一个,我们可以在这里设置是否启用这个断点,也可以给这个断点设置表达式,只有满足表达式时这个断点才中断
比较灵活的是,vscode支持实时设置断点,也就是说你可以在程序运行过程中设置断点
其实重点在于调试控制面板,从左到右依次如下
| 属性 | 介绍 |
|---|---|
| 继续 | 继续运行程序,一直运行到下一个断点,或者程序结束 |
| 单步跳过 | 程序继续运行一行代码 |
| 单步跳入 | 程序进入这个方法的实现,继续运行一行代码 |
| 单步跳出 | 程序跳出这个方法的实现,回到上一层,并继续运行一行代码(注意,这不是回到上一步,实际上相当于是执行完当前的方法,回到上一层,然后中断) |
| 重启 | 重新启动程序 |
| 结束 | 结束调试 |
这里建议完成一次调试来体验这些功能,一般来说我们会使用继续来运行到下一个断点,使用单步跳过来实现一步一步的运行程序,使用单步跳入来进入这个方法,一步一步的完成这个方法。
如果你没有接到任务,你很难觉得调试是一件很重要的事,所以很多人会忽略掉调试
或者说,你其实也是在调试,只不过是人脑调试,比如我们有时候程序遇到bug,会在脑子里一步一步的模拟代码,然后推断程序运行到这里时某个变量应该是多少。
但是你的脑子并不好使(bushi,你会出错,我们可以使用调试工具,可视化这一切过程,我们要在脑子里记得变量,会在界面中给你清晰的展示出来
以本项目为例,假设我们现在想要知道一个unary请求是如何实现的。那么我们可以在请求开始的位置做一个断点
我们可以在client文件夹内的main.go中找到一个rpc.Ping()的方法,在这里设置一个断点,然后按照前面的方法开始跑调试(记得先开server端)
开始调试前,注意当前选中的文件应当是client文件夹内的main.go(或者把launch.json中的program改为这个文件的绝对地址)
调试开始后会在此处停下,然后你可以选择单步跳入进入这个方法的实现,探索具体的实现过程
