之前为了写 Go,我特地捣鼓了一下 VSCode 的 Go 配置,具体的经历可以看 这里。
最近由于业务需求,需要新开一个 Go 的项目。听朋友说 Go 从 1.11 开始有了个叫 Modules 的新特性,于是打算看看能否用在我的新项目中。
为什么我对 Modules 这么感兴趣呢?因为写项目总是逃不开各种包管理,而之前 Go 不管是官方还是非官方的包管理器,都是基于 GOPATH
或者 vendor
目录,也无法很好的解决不同版本的冲突。Modules 据说可以解决这些问题。
我们之前的项目用的是 Go 官方的包管理器 dep
,真是被我们吐槽了好久:
- 它默认不显示进度,除非手动添加
-v
参数; - 命令十分诡异,以安装为例,我见过的有:
npm install
、gem install
、pip install
,还有……dep ensure
; - 我无法把 Go 的项目跟其它项目放在同一个 Workspace 下面,而必须放到
GOPATH
下面。
试用了一下 Modules,发现有这几个好处:
- 它默认在安装时会显示进度,在国内众所周知的网络环境下可以轻松确定网络是否有问题;
- 它是 Go 的原生命令,使用起来跟 Go 的其它命令比较像,没有违和感;
- 它允许我们把 Go 项目放到任意的地方;
- 它有一些很棒的功能,例如生成依赖关系图、生成 vendor 文件夹、验证包的内容、解释为何需要依赖某个包。
对于大部分人来说,照着网上的教程来做就可以了,我在做的时候,遇到了一些问题,于是就在这里记录一下。
VSCode 插件
VSCode 的插件 ms-vscode.go
已经可以完美支持 Go Modules 了,更新到最新版即可。由于我还有项目需要使用 dep
,因此我在 settings.json
里面新增了这些:
{
"go.toolsEnvVars": {
"GO111MODULE": "auto"
},
}
环境变量 GO111MODULE
的取值有三个:off
表示强行使用 GOPATH
的方法(适用于 dep
),on
表示强行使用 Modules,auto
表示如果发现你的项目在 GOPATH
那么就用传统方法(即使有了 go.mod
文件),否则就用 Modules。
报错 no package for import "fmt"
这种错误就比较奇葩了,我相信很多人都遇到过找不到其它包的情况,但我这儿连 fmt
都找不到……
搜了一下,这是 gopls
的报错,于是用 gopls -rpc.trace -v check file.go
看了一下,发现由于我项目文件的问题,报错 initial workspace load failed
,这个 Workspace 里面应当包含 ./...
和 builtin
,fmt
属于后者,因此也跟着找不到了。
那么该如何在项目中引用项目本身的包呢?例如我的项目叫 myproj
,我要在 cmd/main.go
里面依赖 cmd/server
包。
通过搜索,我得知可以在 go.mod
里面配置一行 replace myproj => ./
,整个文件如下:
module myproj
replace myproj => ./
go 1.13
require (
....
)
之后的引用就可以这样写了:
import (
"myproj/cmd/server"
)
最后测了一下,VSCode 插件的各种功能(自动导入、格式化、跳转、调试)都没有什么问题,这就算是大功告成了。至于用起来具体怎么样,还有没有其它的坑,可能得等过一段时间才能知道了。
参考资料
- x/tools/gopls: failure to import package · Issue #32762 · golang/go
- vgo - How do I resolve "cannot find module for path X" importing a local Go module? - Stack Overflow
Update 2021-08-23:对 Delve DAP 的支持
最近 VSCode 的 Go 插件 支持了 Delve 工具的 DAP 协议(dlv-dap
),并且在本地调试的时候默认启用了(远程调试暂时还有问题,所以没有支持),这要求对 launch.json
文件做一点简单的修改:把 mode
改成 "auto"
,删掉 host
和 port
两个字段即可。一份可用的 JSON 配置如下:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug with dlv-dap",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/path/to/main.go",
"cwd": "${workspaceFolder}",
"env": { "some_key": "some_value" },
"args": ["-config=/path/to/some_config.json"],
"showLog": true
}
]
}
试用了一下,DAP 确实比之前的 Legacy 模式要快了一些,并且也修复了一些小问题(例如展开深层嵌套的 map
之前有最大层级限制,现在可以一直展开了)。之后“调试速度”和“用户体验”应该不再会是阻挡使用 VSCode 开发 Go 的负面因素了。