go get 无法拉取私有 Gitea 仓库模块,根本原因是 git 命令无认证权限;需配置 SSH 或 HTTPS 凭据、正确设置 GOPRIVATE=example.com(非 GO_PRIVATE)、require 路径与仓库 URL 完全一致,并建议设 GOPROXY=direct 避免代理干扰。

go get 无法拉取私有 Gitea 仓库模块?先配 git 认证
Go 模块拉取私有 Gitea 仓库时失败,90% 是因为 git 命令本身没权限,不是 Go 的问题。Go 调用 git clone 来下载模块,所以它完全依赖系统级的 Git 凭据配置。
常见错误现象:go get example.com/myorg/mymodule: module example.com/myorg/mymodule: git ls-remote -q origin in /tmp/gopath/pkg/mod/cache/vcs/...: exit status 128: fatal: could not read Username for 'https://example.com': No such device or address
- 用 SSH 方式(推荐):确保
~/.ssh/id_rsa已添加到 Gitea 账户,且git@地址能手动git clone成功 - 用 HTTPS 方式:必须配置
git config --global credential.helper store,然后首次手动git clone https://example.com/myorg/mymodule触发凭据保存 - 别信
GO_PRIVATE能绕过认证——它只跳过代理和校验,不解决鉴权
GO_PRIVATE 和 GOPRIVATE 到底该设哪个?
GOPRIVATE 是 Go 1.13+ 唯一有效的环境变量名,GO_PRIVATE 是旧文档或误传的写法,设了也无效。
使用场景:告诉 Go “这些域名下的模块不走公共代理、不校验 checksum”,但不提供登录能力。
立即学习“go语言免费学习笔记(深入)”;
- 必须设为 Gitea 实例的根域名或通配符,例如:
GOPRIVATE=example.com,*.example.com - 多个域名用逗号分隔,不能有空格
- 如果 Gitea 在子路径(如
https://example.com/gitea),仍只需填example.com,Go 不看路径部分 - 设完后执行
go env GOPRIVATE确认生效,否则go get仍可能尝试走 proxy.golang.org
go.mod 里 require 的路径必须和 Gitea 仓库 URL 完全一致
Go 模块路径不是“逻辑别名”,而是实际拉取地址的映射。如果 require 写错,go get 会按字面去拼 URL,根本不会自动补协议或重定向。
常见错误现象:go: example.com/myorg/mymodule@v0.1.0: reading example.com/myorg/mymodule/go.mod at v0.1.0: unknown revision v0.1.0,其实是因路径大小写、拼写或组织名不匹配导致 404。
- 从 Gitea 页面复制「Clone URL」里的路径部分:比如页面显示
git@gitea.example.com:myorg/mymodule.git,则require应为gitea.example.com/myorg/mymodule v0.1.0 - 如果用 HTTPS 克隆地址是
https://gitea.example.com/myorg/mymodule.git,require也必须用gitea.example.com/myorg/mymodule,不能写成https://gitea.example.com/myorg/mymodule - 路径区分大小写,
MyOrg≠myorg;Gitea 默认小写组织名,但模块路径一旦发布就不可随意改
go proxy 会干扰私有模块?关掉或精准排除
默认开启的 GOPROXY=https://proxy.golang.org,direct 会让 Go 先向公共代理查模块元数据,而私有模块在那根本不存在,浪费时间还可能报错。
性能影响:每次 go list -m all 或 go mod tidy 都会多一次失败的 HTTP 请求,尤其 CI 环境下明显拖慢。
- 最稳妥做法:显式关闭 proxy,只留
direct:GOPROXY=direct - 若需兼顾公有模块加速,可用条件代理:
GOPROXY=https://proxy.golang.org,direct+GOPRIVATE组合已足够,无需额外配置 - 别用
replace临时指向本地路径来“绕过”——这会让依赖图失真,上线构建必然失败
真正卡住的地方往往不是 Go 语法,而是 Git 凭据没通、GOPRIVATE 拼错了域名、或者 go.mod 里 require 的路径和 Gitea 上仓库的实际路径差了一个字母。调试时优先验证 git clone 能否成功,再检查 Go 环境变量输出,最后才动代码。










