有一个问题。Go模块对版本2或更高版本的模块提出了奇怪的命名要求。模块v2 +上的模块名称必须以主版本ala结尾…/v2,并且此规则的通信薄弱。这不是显而易见的,并且整个社区都不了解。

我已经看到许多非常大的项目,包括Google拥有的项目,都弄错了。

我在当地的Go聚会中提出了这个问题,但没人听说过该规则。他们非常怀疑规则是否存在。

很长时间以来,Go一直没有包含用于版本依赖关系的内置方法。它确实包含了有时引起争议 go get的获取软件包的方法。该go get工具直到最近才简单地根据URL克隆了包主分支的HEAD,并将其放在您的$GOPATH。

通常与Go在向后兼容性方面的“极端主义立场”相关联,人们的主要期望是,如果您发布了一个库,则应尽可能保持兼容性。

多年来弹出工具登塔填补这个空白,gopkg.in,滑翔,甚至在同一时间“正式实验” DEP。

dep在Google的支持下,它是依赖管理的继承人。

然而,突然之间,Russ“ rsc” Cox作为正式的Go解决方案vgo(又名Go模块)如雨后春笋般涌向了世界。社区的创建似乎没有任何投入,这让很多人感到cha恼。

尽管dep是一个主要标准中的静脉依赖管理npm之类的,围棋模块的一个决定性的自以为是的“走出去”的解决方案。作为构建步骤,将其作为语言的一部分进行处理。当您go build缺少版本化的依赖项时,构建工具将获取它。

在中列出了依赖性要求,在中列出了所需go.mod的确切版本go.sum。这两个文件都使用其自己的特定于域的语言。先验的语法让人联想到Go本身。后者是用空格分隔的依赖性版本列表,这些版本主要不旨在供人类使用。

构建步骤将根据需要添加到这些文件中,运行go mod tidy将清理它们。

v2 +问题的详细信息
Go模块对程序包开发人员提出了非常奇怪的要求。当模块达到主要版本2或更高版本时,模块名称必须以主要版本结尾。这样做的好处是它创建了一个单独的程序包。结果是,一个项目现在可以依赖同一库的多个主要版本。

实现/v2模块有两种策略:

第一种方法是更改您的模块名称go.mod

可以在github.com/google/go-github上看到一个示例go.mod,看起来很简单,但是还需要您更改包中的任何交叉引用。虽然不是世界末日,但它容易出错,甚至Google都错过了一些机会。

这种方法的最大问题是,它破坏了非模块版本的Go中的子包。随着时间的流逝,这变得不那么重要了,但是在旧版本的Go中,程序包名称必须与它的位置完全匹配。https://github.com/pkg/foo不能github.com/pkg/foo/v2在没有V2目录。Go团队认识到了这一问题,并将基本模块支持修补到Go语言的1.9.7和1.10.3版本中,以帮助简化过渡。

第二种方法和方法的围棋队本身促进离开你的v1项目如在回购的根源,实际上是创建一个v2/包含您的子v2库。

感觉很奇怪,但是优点是它可以与不了解模块的较旧版本的Go完全兼容。在我的头顶上,我只知道有一个项目按此路线进行,而他们似乎又回到了这个项目上。

出于价值考虑,官方的Go Blog试图清除一些情况,并发布了有关此问题的文章。

blog.golang.org/v2-go-modules

即使是经验丰富的开发人员,我也发现此文章有些难以理解。对于此要求多么重要和不同寻常,无法充分访问书面内容。

包括Buildkite在内的许多项目terminal-to-html只是不知道需求,直到他们忘记处理它,并最终发布了残破的发行版。具有go.mod文件但不遵守模块v2 +规则的v2 + Go库对于依赖者而言是编译时错误。对于用户而言,这比不成为Go模块要糟糕。

诸如GORM之类的某些项目通过将其2.0版本标记为遥不可及的1.x版本,完全避开了该问题。某种解决方案,但闻起来很糟糕。

怎么办?
首先,我认为围棋团队需要做得更好,以阐明该规则。他们需要从屋顶尖叫。他们至少需要文档的一部分,以通俗易懂的方式对其进行清楚地布置。

除此之外,Go工具还有警告的余地。导入较旧版本的根包的子包应引发警告。错过一个问题太容易了。

尽管有用性值得怀疑,但godoc.org / pkg.go.dev上仍有类似注释的余地。

最好和最不可能的选择是Go删除需求并将其设为可选。我相信这是一个可行的解决方案。想要允许用户包括多个版本的软件包可以遵循v2准则,而其他则不需要。

我个人会提倡但也可能永远不会发生的一个选择是要求/v0并且/v1同样如此,这样您就可以立即解决问题,而不是花费多年的时间来完成一个项目。尽早教公约。