package.json 对比 go.mod:版本字段去哪儿了?

如果你从 JavaScript 转到 Go,有一件事会让你感到惊讶。

打开一个 package.json 文件。你会看到顶部有一个 version 字段。它易于阅读,你可以在 pull request 中修改它。它就存在于你的代码之中。

现在打开一个 go.mod 文件。

版本信息并不在那里。这不是一个错误,而是一种选择。

Go 不会为你的模块使用版本字段,而是使用 git tags。

工作原理: • 你运行 git tag v1.2.3 • 你将 tag 推送到你的仓库 • 该 tag 就成为了你的版本

当有人运行 go get 时,Go 会查看你的 git tags 来寻找正确的 commit。该 tag 是唯一的真相来源 (single source of truth)。

这种设计有一个巨大的优势:版本永远不会指向错误的代码。在 npm 中,发布的代码和版本字段可能会出现脱节。而在 Go 中,它们是同一回事。版本即 commit。

然而,这改变了你的工作流:

示例: v1 使用 github.com/you/my-app v2 使用 github.com/you/my-app/v2

这允许一个程序在不产生冲突的情况下,使用同一个库的两个不同的主版本。

大多数其他语言都将版本保留在文件中: • Node: package.json • Rust: Cargo.toml • Python: pyproject.toml • Java: pom.xml

Go 是个异类。它严格依赖 git tags。

如果你怀念 npm 的体验,可以在构建时使用 ldflags 将版本注入到你的二进制文件中。这样你的应用就可以响应版本查询命令了。

权衡很简单: 版本字段易于阅读和审查,但它可能会“撒谎”。 git tag 难以察觉,但它永远真实。

Go 选择真实,而非便利。

致 Go 开发者:这是最好的模型吗?如果工具能根据 git tag 验证它,你会更倾向于在 go.mod 中使用版本字段吗?

Source: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301