-
Notifications
You must be signed in to change notification settings - Fork 16
在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
改为这个文件的绝对地址)
调试开始后会在此处停下,然后你可以选择单步跳入
进入这个方法的实现,探索具体的实现过程