Go模块发布本质是Git打符合semver的v开头tag并确保go.mod路径与仓库一致,v2+需显式体现于import路径,私有模块须配置GOPRIVATE及代理策略。

Go 模块打包本质是版本化代码发布,不是传统“打包成 zip”
Go 没有类似 npm pack 或 python setup.py sdist 的本地归档打包命令。所谓“模块打包”,实际是指:把代码托管到 Git(如 GitHub/GitLab),打上符合 semver 规范的 tag(如 v1.2.0),并确保根目录含 go.mod 文件。Go 工具链会自动从该 tag 下载源码并缓存——这才是 Go 模块分发的真实路径。
常见误解是试图用 tar 或 zip 手动压缩后上传,这会导致 go get 失败或版本识别异常。
-
go.mod必须存在且module声明与仓库地址一致(例如 GitHub 仓库github.com/user/repo,则go.mod中必须为module github.com/user/repo) - 打 tag 前需运行
go mod tidy清理未使用依赖,避免下游go get时拉取错误间接依赖 - tag 名必须以
v开头(v0.1.0、v2.0.0),否则go list -m -versions不识别
发布前验证模块可被正常 fetch
在 push tag 到远程前,应本地模拟下游行为,确认模块能被正确解析和下载。关键检查点不是“能不能编译”,而是“能不能被其他项目 go get 成功”。
常用验证步骤:
立即学习“go语言免费学习笔记(深入)”;
- 新开临时目录,执行
go mod init testmod - 运行
go get github.com/yourname/yourrepo@v1.2.0(注意带@vX.Y.Z) - 若报错
unknown revision v1.2.0,说明 tag 未 push;若报错malformed module path,大概率是go.mod中module声明与实际 URL 不匹配 - 成功后检查
go.sum是否生成对应条目,且校验和有效
处理 v2+ 版本需显式声明 major 子目录
Go 要求 v2 及以上主版本必须体现在 import 路径中,否则 go get 会拒绝识别。这不是可选约定,而是强制语义规则。
例如发布 v2.0.0,必须满足以下任一条件:
- 将代码移到子目录
/v2,并在该目录下放go.mod,其中module为github.com/user/repo/v2 - 不挪目录,但用
go mod edit -module github.com/user/repo/v2修改根go.mod,再打v2.0.0tag(此时所有 import 必须写成import "github.com/user/repo/v2")
跳过这步直接打 v2.0.0 tag,下游执行 go get github.com/user/repo@v2.0.0 会提示 no matching versions for query "v2.0.0"。
私有模块分发需配置 GOPRIVATE 和代理策略
公司内部模块若托管在私有 Git(如 gitlab.internal/mygroup/lib),默认会被 Go 代理(proxy.golang.org)拦截并返回 404。必须显式告诉 Go “哪些域名不走代理”。
典型配置方式:
- 设置环境变量:
GOPRIVATE=gitlab.internal(支持通配符,如GOPRIVATE=*.internal) - 若同时用
GOPROXY(如https://goproxy.cn),需确保它支持私有域名回退,否则要设为GOPROXY=https://goproxy.cn,direct,让失败时直连 - 对 SSH 地址(如
git@gitlab.internal:mygroup/lib.git),还需配置~/.netrc或git config --global url."git@gitlab.internal:".insteadOf "https://gitlab.internal/",否则go get无法认证
模块发布最易忽略的是路径与版本的耦合性:一个 v2 模块一旦被下游导入为 /v2,就不能再通过修改 tag 让它“变回 v1 路径”。版本号、import 路径、go.mod 声明三者必须严格同步,差一点就会导致依赖解析失败且错误信息极其模糊。










