直接设goproxy=direct不等于能用私有模块,因go仍会校验checksum且git层无认证;必须同时配置goprivate、确保git凭据有效、模块路径与url严格一致。

为什么直接设 GOPROXY=direct 不等于“能用私有模块”
很多人以为局域网里只要把 GOPROXY=direct 就万事大吉,结果 go get git.corp.internal/utils 还是报 401 Unauthorized 或 unknown revision。这不是 Go 的 bug,而是混淆了两个独立环节:Go 工具链决定“要不要走代理”,而真正拉代码的是系统 git 命令——它根本不知道你的 token 或 SSH 密钥在哪。
必须同时满足三件事:GOPRIVATE 告诉 Go 别转发请求、git 能凭认证直连仓库、私有模块的 go.mod 中 module 名与仓库 URL 严格一致。缺一不可。
部署 athens 比 goproxy 更适合企业内网
athens 是 CNCF 孵化项目,原生支持私有模块缓存(goproxy 默认不缓存非公开域名),且能对接 LDAP/OAuth2,适合审计要求高的环境。部署时注意三点:
- 启动命令中必须显式指定
-exclude参数,否则它会尝试校验所有模块(包括私有模块)并失败:athens -config /etc/athens/config.toml -exclude="*.corp.internal,gitlab.example.com/**"
-
config.toml里proxy.mode = "sync"(非async),避免 CI 构建时模块还没写入缓存就返回 404 - HTTP 端口(默认
:3000)需在内网 DNS 统一解析为athens.internal,所有客户端配GOPROXY=http://athens.internal:3000,别用 IP——否则go mod download会因证书或 Host 头不匹配失败
GOPRIVATE 写错一个字符就全盘失效
常见错误不是没设,而是格式错得隐蔽:
-
GOPRIVATE=git.corp.internal/*→ 只匹配一级路径,git.corp.internal/team/lib会被忽略;应写成git.corp.internal/** -
GOPRIVATE="git.corp.internal, gitee.com/my-team"→ 逗号后空格导致 Linux 下只生效第一个域名 -
GOPRIVATE=*.corp.internal→ Go 不支持通配符前缀,必须写全主域名 - 多域名必须英文逗号分隔、无空格、无引号(Windows PowerShell 除外),正确写法:
go env -w GOPRIVATE=git.corp.internal/**,gitee.com/my-team/**
验证私有模块是否真被 athens 缓存住
别只信 go build 成功——它可能从 vendor/ 或本地 modcache 读取。要确认 athens 在起作用,执行:
- 清掉本地缓存:
go clean -modcache - 临时禁用 vendor:
go env -u GOFLAGS(如果之前设过-mod=vendor) - 触发一次新拉取:
go get git.corp.internal/utils@v1.2.0 - 立刻查 athens 日志:
journalctl -u athens -n 50 --no-pager | grep "git.corp.internal",看到INFO cache.go:123 saved module才算真正落库
最易被忽略的是:athens 默认不缓存 replace 指向的本地路径或 file:// 模块,这类依赖必须提前用 go mod vendor 固化,不能指望代理服务解决。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











