Go模块发布本质是Git打符合semver的v开头tag并确保go.mod路径与仓库一致,v2+需显式体现于import路径,私有模块须配置GOPRIVATE及代理策略。
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)go mod tidy 清理未使用依赖,避免下游 go get 时拉取错误间接依赖v 开头(v0.1.0、v2.0.0),否则 go list -m -versions 不识别在 push tag 到远程前,应本地模拟下游行为,确认模块能被正确解析和下载。关键检查点不是“能不能编译”,而是“能不能被其他项目 go get 成功”。
常用验证步骤:
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 是否生成对应条目,且校验和有效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.0 tag(此时所有 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"。
公司内部模块若托管在私有 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,让失败时直连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 声明三者必须严格同步,差一点就会导致依赖解析失败且错误信息极其模糊。