本文适用于go version go1.15.2 darwin/amd64
下载 Go
因为Mac可以使用Homebrew来安装Go,所以直接执行以下命令来安装Go:
brew install go
此时可能会卡在Updating Homebrew,可以通过切换中科大源来解决:
// 替换brew.git:
cd "$(brew --repo)"
git remote set-url origin https://mirrors.ustc.edu.cn/brew.git
// 替换homebrew-core.git:
cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-core.git
然后就可以顺利安装了。安装完成后,可以在终端执行以下命令来测试:
go version
此时会在终端显示go版本:
Go环境变量配置
在Go 1.13之后,无需再通过设置系统环境变量的方式来修改,可以通过go env -w 命令来设置Go的环境变量。
需要设置的环境变量如下:
// 用于存放依赖包以及编译文件,比较随意,只要不和GOROOT重名即可,官方禁止这一行为
go env -w GOPATH=/Users/系统用户名/Library/go
// 设置代理后,在未翻墙的情况下,打开vscode后gopls工具的加载会很快
go env -w GOPROXY=https://goproxy.cn,direct
Vscode插件安装
在插件商店中搜索Go,并点击安装即可:
安装delve
Devle是一个非常棒的golang 调试工具,支持多种调试方式,直接运行调试,或者attach到一个正在运行中的golang程序,进行调试。
线上golang服务出现问题时,Devle是必不少的在线调试工具,如果使用docker,也可以把Devle打进docker镜像里,调试代码。
在命令终端terminate中执行以下安装命令,进行delve的安装。
$ go get -u github.com/go-delve/delve/cmd/dlv
设置 launch.json 配置文件
command + shift + p 调出下拉列表,输入或者选择 Debug: Open launch.json,打开 launch.json 文件,如果第一次打开,会新建一个配置文件,默认配置内容如下
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"env": {},
"args": []
}
]
}
可能用到的属性介绍
启动配置必须具有的属性
每个启动配置都必须具有以下属性:
type - 用于此启动配置的调试器的类型,如python,go,Java等。每安装调试扩展引入一个类型:node用于内置节点调试器,例如,或php与go对PHP和去扩展。
request - 此启动配置的请求类型。目前,launch并且attach受到支持。
name - 阅读器友好名称,显示在“调试启动配置”下拉列表中。
可选属性
以下是可用于所有启动配置的一些可选属性:
preLaunchTask- 要在调试会话开始之前启动任务,请将此属性设置为tasks.json中指定的任务的名称(在工作空间的.vscode文件夹中)。
postDebugTask- 要在调试会话的最后启动任务,请将此属性设置为tasks.json中指定的任务的名称(在工作空间的.vscode文件夹中)。
internalConsoleOptions - 此属性控制调试会话期间“调试控制台”面板的可见性。
debugServer- 仅适用于调试扩展作者:此属性允许您连接到指定的端口,而不是启动调试适配器。
常用到的一些属性
许多调试器支持以下某些属性:
program - 启动调试器时要运行的可执行文件或文件
args - 传递给程序进行调试的参数
env- 环境变量(该值null可用于“取消定义”变量)
cwd - 当前工作目录,用于查找依赖项和其他文件
port - 连接到正在运行的进程时的端口
stopOnEntry - 程序启动时立即中断
console-要使用什么样的主机,例如internalConsole,integratedTerminal或externalTerminal
常见属性如下
name 调试界面下拉选择项的名称(在最上面的DEBUG和设置按钮中间)
type 设置为go无需改动,是 vs code 用于计算调试代码需要用哪个扩展
mode 可以设置为 auto, debug, remote, test, exec 中的一个
program 调试程序的路径(绝对路径)
env 调试时使用的环境变量。例如:{ "ENVNAME": "ENVVALUE" , "go.gopath":"/Users/xx/go/src/xxx/项go项目名/cmd/http/main.go"}, // 调试时使用的环境变量。例如:{ "ENVNAME": "ENVVALUE" },gopath要指向本次要调试项目的主入口,即main.go所在的绝对路径
envFile 包含环境变量文件的绝对路径,在 env 中设置的属性会覆盖 envFile 中的配置
args 传给正在调试程序命令行参数数组
showLog 布尔值,是否将调试信息输出
logOutput 配置调试输出的组件(debugger, gdbwire, lldbout, debuglineerr, rpc),使用,分隔, showLog 设置为 true 时,此项配置生效
buildFlags 构建 go 程序时传给 go 编译器的标志
remotePath 远程调试程序的绝对路径,当 mode 设置为 remote 时有效
在 debug 配置中使用 VS Code 变量
${workspaceFolder} 调试 VS Code 打开工作空间的根目录下的所有文件
${file} 调试当前文件
${fileDirname} 调试当前文件所在目录下的所有文件
使用构建标记(build tags)
如果需要使用构建标记(e.g. go build -tags=whatever_tag)在参数 buildFlags 里写入 -tags=whatever_tag" 即可,支持多标签,使用单引号将标签包围,例如: "-tags='first_tag second_tag third_tag'"
debug 配置代码片段
可以在 launch.json 文件中,使用 Go 关键词调出 debug 配置项的代码片段。
调试当前文件配置片段
{
"name": "Launch file",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${file}"
}
调试单个测试用例配置片段
{
"name": "Launch test function",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}",
"args": [
"-test.run",
"MyTestFunction"
]
}
调试包中所有的测试用例配置片段
{
"name": "Launch test package",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}"
}
调试构建二进制文件配置片段
{
"name": "Launch executable",
"type": "go",
"request": "launch",
"mode": "exec",
"program": "absolute-path-to-the-executable"
}
远程调试
远程调试需要在launch.json中将模式设置为远程"mode":“remote”,并且还需要服务器上起一个无头的 Delve 服务
例如:
$ dlv debug --headless --listen=:2345 --log --api-version=2
如果需要传参数到程序中,则需要将参数传入到 Delve 服务中
例如:
dlv debug --headless --listen=:2345 --log -- -myArg=123
launch.json 配置如下:
{
"name": "Launch remote",
"type": "go",
"request": "launch",
"mode": "remote",
"remotePath": "服务器调试文件的目录(绝对路径)",
"port": 2345,
"host": "127.0.0.1",
"program": "本地调试文件所在的目录(绝对路径)",
"env": {}
}
将上述配置中的 host 和 port 修改 成Delve 服务所在的服务器ip和其监听的端口号。
remotePath 应该配置为调试文件的绝对路径
program 需要配置本地机器文件所在的绝对路径,是 remotePath 的一个副本
配置完成后,点击调试按钮,VS Code 将会向远程的 dlv 服务发出调试指令,而不是使用本机的 dlv 实例。
调试过程
在要进行调试的自定义函数或者自定义变量处,设置断点,断点的数目可以设置多个(注意,不要在开源的包中实现的方法处打断点,要不然调用栈会一直深入到开源实现的底层函数/变量处)。然后 Fn + F10(step over)进行单步调试(单步调试会跳过本次不执行的分支),左边栏中的VARIABLES变量中可以看到各个变量值的变化。如果想要进入到当前调试行中的函数里面,可以使用Fn + F11(step into)调入函数,不再想要执行函数内的语句,则可以 Fn + Shift+F11 (Step out ) 直接跳出当前函数,跳到上一次进入处的下一条语句。
注意:尽管在launch.json中定义了主函数main.go的绝对路径,但是在调试时,仍然想要先打开main.go程序,然后在启动调试Fn + F5后,跳转到要调试的程序处,接着可以选择单步调试Fn + F10或者进入函数Fn + F11,跳出函数Fn + shift + F11。通常,如果断点处又调用了其他自定义的函数,可以在分别在这个调用函数处和函数定义内部的其他函数调用/变量处打上多个断点,接着进行调试。
参考
https://code.visualstudio.com/Docs/editor/debugging
https://juejin.im/entry/5aa1f98d6fb9a028c522c84b
https://segmentfault.com/a/1190000018671207
https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code#sample-configuration-to-debug-a-single-test
https://github.com/go-delve/delve/tree/master/Documentation/installation