不要把你的 Go 代码和 GitHub 绑在一起
Go 采用完整 URL(通常是 GitHub 路径)作为导入标识符的做法,引发了人们对长期稳定性、供应商锁定,以及仓库迁移时痛苦的担忧。评论者讨论了自定义域名、内部代理和 vendoring 依赖等替代方案,指出它们在韧性、安全性、便利性和维护负担之间存在权衡。许多人认为没有任何命名空间能做到绝对无故障,因此真正的挑战在于设计出能让托管变更和依赖保留在长期内更易管理的工具与工作流。
Go 导入路径与 GitHub 绑定
- Go 的“import == network path”设计,使仓库托管主机成为 API 表面的一部分。
- 许多人认为这很脆弱:从 GitHub 迁移到其他 forge(甚至只是组织改名),就意味着要跨多个仓库和历史标签修改导入路径,破坏旧构建。
- 也有人认为问题被夸大了:一次罕见迁移,加上搜索/替换或
go.mod replace的额外工作量是可以接受的。
自定义域名 / 虚荣 URL
- 支持虚荣域名的观点:使用自己的域名可以将身份与任何单一 forge 解耦;以后可以通过 DNS 或简单的 web 处理器(nginx、Hugo 模板、vanity URL 服务器)把流量重定向到新主机,甚至重定向到制品仓库。
- 批评者担心这只是把单点故障转移了:域名可能过期,注册商可能删除顶级域或提高价格,被废弃的域名也可能被接管并滥用。
- 对于封闭/内部代码,控制域名被认为更合理;对于长期存在的开源软件,一些人更偏好像 GitHub 这样的“稳定大平台”。
Vendoring、代理与可复现性
- 有人主张为每个 Go 项目都 vendor 依赖:这样能改善离线构建、增强对上游消失的韧性,并加强供应链控制。
- 也有人指出其缺点:仓库膨胀、git 操作和 CI 变慢、需要手动更新,以及递归依赖复杂性。
- Go 的模块代理(
proxy.golang.org)和内部镜像被提为折中方案:缓存一次,然后构建时不必直接访问 GitHub。
迁移痛点与组织规模
- 多位评论者把真实迁移(GitHub → 其他主机、域名变更)描述为在大规模下“很糟糕”,尤其是当许多仓库和版本彼此依赖时。
- 简单的搜索/替换会失效,因为你需要保留重建历史版本的能力;最后你会不得不为旧提交分支/打标签,只为了重写导入路径。
- 每个依赖只保留单一版本的 monorepo 可以避免部分问题,但也带来了自身成本。
安全性、完整性与包管理系统设计
- 引发担忧的点包括:
- 失效或被劫持的域名/主机提供恶意代码。
- Go 依赖位置而不是稳定标识符或内容寻址。
- 建议的改进包括:内容可寻址导入、在
go.mod中加入哈希(不仅仅是go.sum)、签名模块、更好的重定向/别名机制,或者回退到像 Software Heritage 这样的归档。 - 有人认为 Go 的包生态是一个设计不足的系统,后续不断叠加功能(modules、proxies、
replace),而不是一个连贯的、基于注册表的设计。