R·ex / Zeng


音游狗、安全狗、攻城狮、业余设计师、段子手、苦学日语的少年。

Go module 踩坑备忘

注意:本文发布于 1542 天前,文章中的一些内容可能已经过时。

之前为了写 Go,我特地捣鼓了一下 VSCode 的 Go 配置,具体的经历可以看 这里

最近由于业务需求,需要新开一个 Go 的项目。听朋友说 Go 从 1.11 开始有了个叫 Modules 的新特性,于是打算看看能否用在我的新项目中。

为什么我对 Modules 这么感兴趣呢?因为写项目总是逃不开各种包管理,而之前 Go 不管是官方还是非官方的包管理器,都是基于 GOPATH 或者 vendor 目录,也无法很好的解决不同版本的冲突。Modules 据说可以解决这些问题。

我们之前的项目用的是 Go 官方的包管理器 dep,真是被我们吐槽了好久:

  • 它默认不显示进度,除非手动添加 -v 参数;
  • 命令十分诡异,以安装为例,我见过的有:npm installgem installpip 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 里面应当包含 ./...builtinfmt 属于后者,因此也跟着找不到了。

那么该如何在项目中引用项目本身的包呢?例如我的项目叫 myproj,我要在 cmd/main.go 里面依赖 cmd/server 包。

通过搜索,我得知可以在 go.mod 里面配置一行 replace myproj => ./,整个文件如下:

module myproj

replace myproj => ./

go 1.13

require (
    ....
)

之后的引用就可以这样写了:

import (
    "myproj/cmd/server"
)

最后测了一下,VSCode 插件的各种功能(自动导入、格式化、跳转、调试)都没有什么问题,这就算是大功告成了。至于用起来具体怎么样,还有没有其它的坑,可能得等过一段时间才能知道了。

参考资料

Update 2021-08-23:对 Delve DAP 的支持

最近 VSCode 的 Go 插件 支持了 Delve 工具的 DAP 协议(dlv-dap,并且在本地调试的时候默认启用了(远程调试暂时还有问题,所以没有支持),这要求对 launch.json 文件做一点简单的修改:把 mode 改成 "auto",删掉 hostport 两个字段即可。一份可用的 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 的负面因素了。

Disqus 加载中……如未能加载,请将 disqus.com 和 disquscdn.com 加入白名单。

这是我们共同度过的

第 3088 天