R·ex / Zeng


音游狗、安全狗、攻城狮、业余设计师、段子手、苦学日语的少年。 MUGer, hacker, developer, amateur UI designer, punster, Japanese learner.

Go module 踩坑备忘

最近由于业务需求,需要新开一个 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 插件的各种功能(自动导入、格式化、跳转、调试)都没有什么问题,这就算是大功告成了。至于用起来具体怎么样,还有没有其它的坑,可能得等过一段时间才能知道了。

参考资料

版权声明:除文章开头有特殊声明的情况外,所有文章均可在遵从 CC BY 4.0 协议的情况下转载。
上一篇: Redirect attack - Shadowsocks 流密码的不安全因素
下一篇: 用 OpenResty+OpenCC 让网站支持正体中文

这是我们共同度过的

第 1801 天