惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cyber Attacks, Cyber Crime and Cyber Security
Cisco Talos Blog
Cisco Talos Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
T
Tenable Blog
PCI Perspectives
PCI Perspectives
Simon Willison's Weblog
Simon Willison's Weblog
N
News and Events Feed by Topic
Know Your Adversary
Know Your Adversary
S
Schneier on Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Privacy International News Feed
C
CERT Recently Published Vulnerability Notes
NISL@THU
NISL@THU
SecWiki News
SecWiki News
S
Securelist
D
Docker
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
T
Tailwind CSS Blog
T
Troy Hunt's Blog
The Register - Security
The Register - Security
K
Kaspersky official blog
Blog — PlanetScale
Blog — PlanetScale
云风的 BLOG
云风的 BLOG
Hacker News: Ask HN
Hacker News: Ask HN
S
Secure Thoughts
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
博客园 - 司徒正美
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
F
Fortinet All Blogs
T
Threatpost
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
小众软件
小众软件
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 聂微东
Attack and Defense Labs
Attack and Defense Labs
B
Blog RSS Feed
Project Zero
Project Zero
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
博客园 - 【当耐特】
V
V2EX
Help Net Security
Help Net Security
P
Proofpoint News Feed
A
Arctic Wolf

Tony Bai

重磅!Tokio官方发布全栈框架Topcoat:不用WASM,AI时代Rust也能“糊”网页了 软件工厂的明与暗:当代码可以自动生产,人类为何必须留下一盏灯? Twitter之父再出手:Block开源Buzz,要让人类和AI Agent「同工同权」 Go 密码学维护者放大招:把 Passkey 存成一行字符串,还顺手为 Go 1.28 写好了 API Loop Engineering才火两个月,硅谷已经卷出“Graph Engineering”了 我开源了 cc-session-migrate :让 Claude Code 会话在多台机器之间自由迁移 从掌上设备的失败到AI时代的基石:Java官方纪录片,揭开一门语言30年的生死赌局 “皇帝的新衣”一年后:对话Thorsten Ball谈Agentic编程 告别标签页焦虑:我让 AI 帮我做了个浏览器插件 TabQueue Bun刚把Zig重写成Rust,这个团队却用487天反向重写 为了一个函数名,Go官方吵了两个月:maps.Same提案近日正式通过 Go 1.28 路线图首度曝光:Cgo 告别C工具链?泛型容器将入标准库? 掌控外环:为什么“循环工程”的边界必须由人类死守? 171个“已批准”却迟迟未实现的提案:Go语言的十年“欠账清单” 别再往 Go 里塞 Java 了:拆解 spf13 的 Idiomatic Go 信仰 AI 不在乎代码烂不烂,但你的Token账单在乎:一项660次实验揭示的编程新常识 10倍速 TypeScript 7.0 正式发布,前Go产品经理:Go才是AI智能体时代的“天选语言” Bun 重写为 Rust 后,Zig 之父罕见开炮:“我们早就等着看你重写” 全新 AI 技术栈:模型、Harness、Loop 与自我进化的智能体 AI 重写 Bun 为Rust全过程揭秘:101万行代码、11天、64个Claude并行开工 MCP Server 架构模式全解析:5 种模式、4 个反模式,与那条不能越过的“工具数量红线” 从手动 govanityurls + Nginx 迁移到 gvu:一次真实迁移记录 从“切歌小工具”到“零人工代码”:Claude Code 的诞生史,比科幻还科幻 如何使用 Claude Code 构建 AI 循环系统(Loops) 5 分钟上手 gvu:把 vanity import path 这件事,从“半天运维”变成一条命令 Go 对语言演化的保守态度,在未来 5 年是否仍然正确呢? 五年,三篇文章,一个我一直没真正解决的问题 别把“容易”当“简单”:Gin 框架作者撰文揭秘 88k Star 背后的架构哲学 每个 AI 工程师都应该知道的 20 个循环设计模式 cc-switch-cli:专为终端控与远程开发打造的 Claude Code 多模型切换工具! Andrej Karpathy 解析 Loop Engineering:构建“数日级”长程 Agent 的 9 条黄金法则 HashiCorp 创始人:AI 时代,我们为什么越来越需要有“品味”的程序员? HashiCorp 创始人:AI 时代,我们为什么越来越需要有“品味”的程序员? 一个 Rust 项目吃掉 75GB 硬盘?聊聊 Go 与 Rust 的“缓存焦虑”与拯救指南 折腾过各种语言后,我为什么总是回到 Go 语言? YC 揭秘 AI 原生组织:打造一家在睡梦中自我进化的公司 从 WordPress 到 Hugo:一个 20 年技术博客的迁移实录 偿还十年技术债:深度拆解 Go 1.27 的 GODEBUG 强力清理计划 浏览器里的“安全阴谋”:为什么 Go 1.27 的 UUIDv7 会离奇丧失随机性? Go 1.27新特性前瞻:泛型方法落地,标准库内建 UUID - Tony Bai AI 正在撕裂研发团队:狂欢的“托管派”与心碎的“守夜人” - Tony Bai 屠榜 CNCF!为什么在云原生时代,Go 语言能把 Java、C++ 和 Rust 堵在门外? 上千程序员自爆 AI 的“卧槽时刻”:是推开神界大门,还是跌入黑盒地狱? - Tony Bai 大模型正在见顶!传奇架构师:欢迎来到“平坦曲线时代” - Tony Bai Anthropic 40万大样本揭秘:AI 时代为什么“专家”身价暴涨? - Tony Bai 在 AI 编码时代,为什么我们依然选择 Go 而不是 Rust? DeepMind 亮出王炸:别再手写 Agent Harness 了,AI 已经学会自己写了! 为什么说“编译通过,就能运行”?Google 专家 Alice 揭秘 Rust 的工程美学与底层逻辑 谷歌 SRE 重磅白皮书:当 AI 自动写出 10 倍代码,谁来阻止系统崩溃? 别再省 Token 了!硅谷新共识:浪费算力才是唯一捷径 - Tony Bai Linux 内核顶级维护者:写了 35 年 C,是 Rust 让我重新找回了编程的乐趣 拒领上亿、封杀 AI:Zig 之父为什么 10 年不发 1.0? 写地道的 Go 语言,是否能让你成为了一个更好的开发者? - Tony Bai RSA 将死?Let’s Encrypt 押注 MTCs 迎战后量子时代 C++ 的权力游戏:一部关于妥协、背叛与重生的“史诗神剧” - Tony Bai 终结十年纠结:Go 新提案允许 Example 支持任意函数签名 - Tony Bai 2026年,大厂重构核心系统为何集体投向 Go? - Tony Bai “辛辛苦苦考上985,却发现AI能替代我90%的工作”:今天的高考,我们还在为什么而战? - Tony Bai 传奇黑客 Geohot 炮轰 AI Agent:这是软件工程史上代价最昂贵的灾难! 别把 Go 写成 Java:毁掉项目从过度架构开始 - Tony Bai 开源维护者的困境 - Tony Bai AI 时代如何真正掌握一门新技术?这份非主流学习指南建议永久收藏 - Tony Bai Go 生态17年大浪淘沙:2026年最值得引入的10个“神仙级”QoL工具包 - Tony Bai 再见样板代码!Go 官方新提案:函数一键转接口 - Tony Bai 写代码快 10 倍,不等于研发快 10 倍!Google 揭秘 AI 系统级瓶颈 Google I/O 2026:Jeff Dean 携 DeepMind 众神宣告,AI Agent 正在终结“标准化软件”时代 AI 优化 1.5ms,手写 0.02ms!Ghostty 作者痛批 AI 编程“平庸陷阱” Redis 之父吐槽现代前端的复杂性:我们到底是在解决问题,还是在制造问题? - Tony Bai 无痛消灭技术债:Google I/O 2026 开启 Go 自动重构时代 省下 10% CPU!Uber 揭秘 Go 栈扩容的隐秘代价 从 Go 迁移到 Rust - Tony Bai 悄悄用 Go 重写 AI 基础设施:NVIDIA 的 GPU 云平台为何选择 Go? Shopify 23,000 名工程师背后的 Claude Code 配置方案(你可以直接复刻的完整配置) Google 开源 AX 与 Agent Substrate:构建以 Agent 为核心的云原生计算底座 十年难题终获突破:揭秘 Go 1.27 接口逃逸分析优化 - Tony Bai
Go 私有模块拉取全解:凭据配置 + Vanity URL,个人与组织全覆盖
Tony Bai · 2026-07-08 · via Tony Bai

题图

本文永久链接https://tonybai.com/2026/07/08/go-private-modules-comprehensive-guide

大家好,我是Tony Bai。

Go 语言的依赖管理从 GOPATH 时代走到 Go Modules,公共依赖的拉取体验已经足够顺滑,但只要涉及“私有模块”,绝大多数团队和个人开发者都会在某个时刻撞上同一堵墙。

具体来说,大概率是下面这几个痛点里的一个或几个:

  • 凭据配置散落各处:.netrcgit config、CI 环境变量里都可能藏着一份 token,换一台机器、换一个 CI 平台,就要重新配一遍,稍不注意还容易把明文 token 提交进仓库;
  • import path 和代码托管平台强绑定:go.mod 里写死了 github.com/yourname/xxx,哪天想把仓库从 GitHub 挪到自建 GitLab 或者 Codeberg,所有依赖这个模块的代码都要跟着改 import path;
  • 想要有自己域名语义的 import path,又不想为此单独运维一套服务:自己写静态页面维护成本高,自建 govanityurls + Nginx 又要操心证书续期、单点故障;
  • 组织规模变大之后,新增一个私有模块的映射变成一件琐事:改配置、重载服务,团队人数越多,这类重复劳动的隐性成本越明显;
  • 代码需要跨组织边界分发时(比如交付给客户),原有的私有拉取方案在对方网络环境里直接失效,需要临时重新搭一遍。

这篇文章尝试把这件事一次性讲透,分三部分:

  • 第一部分是不分场景都要搞清楚的凭据配置底层机制;
  • 第二部分是个人开发者的几种典型场景;
  • 第三部分是组织 / 团队场景。

每种场景我都会给出对应的落地方案,上面这几个痛点,也会在对应的小节里逐一给出解法,供你按需查阅、按需收藏。

统一的凭据配置方案

在讨论任何具体场景之前,有必要先把几个容易混淆的环境变量和凭据配置方式讲清楚,因为后面所有场景本质上都是在这个底层机制上做排列组合。

两种主流的凭据配置方式

方式一:~/.netrc

这是最传统的方式,gitgo 命令本身都会读取这个文件:

machine github.com
login your-username
password ghp_your_personal_access_token

以github.com为例,其中的password你可以在“Developer Settings”的“Personal access tokens”中申请,推荐使用“Fine-grained personal access tokens”,你可以更好地控制token的权限粒度。

方式二:git configinsteadOf 重写

更推荐这种方式,因为它可以精确控制到某个域名 / 某个协议,而不是一个笼统的凭据文件:

git config --global url."https://oauth2:${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"

如果你更习惯 SSH 方式(配好 deploy key 之后),可以让 HTTPS 的拉取请求自动重写成 SSH:

git config --global url."ssh://git@github.com/".insteadOf "https://github.com/"

CI 环境里,建议把 token 放进 CI 平台自带的 secret 变量,而不是明文写进仓库里的脚本文件,这是最基本的安全底线。

四个环境变量,职责边界要分清楚

这是整篇文章最重要的一个知识点,后面所有场景都建立在这个区分之上:

  • GOPRIVATE:告诉 Go 工具链,哪些 module 路径前缀属于私有模块,遇到这些路径时跳过公共 GOPROXYGOSUMDB,直接走版本控制工具(git)直连拉取。例如:
export GOPRIVATE=github.com/yourname/*,go.mycompany.com/*
  • GOPROXY:控制 module 内容本身怎么拉取、怎么缓存,默认是 https://proxy.golang.org,direct。如果你在公司内部有自己的私有代理(Athens、goproxy/goproxy.cn等),一般会配成类似 https://your-internal-proxy,direct 这样的组合。

  • GOSUMDB:控制是否要向 sum.golang.org 做校验和验证,私有模块通常需要连同 GOPRIVATE 一起把这一层也关掉,否则公共校验服务器根本没有你私有模块的记录,会导致拉取失败。

  • GOVCS:Go 1.16 引入的安全限制,控制哪些路径允许用哪种版本控制工具拉取,默认只允许公共托管平台走 git/hg 等,私有域名如果不在白名单里,可能需要显式配置,例如:

export GOVCS=go.mycompany.com:git

简单总结一下这四者的关系:GOPRIVATE 划定“哪些是私有的”,GOPROXY/GOSUMDB 决定“公共部分怎么拉、怎么校验”,GOVCS 决定“私有部分允许用什么工具拉”。

理解了这一层,后面无论是个人场景还是组织场景,本质上都只是在“私有仓库放在哪里”和“import path 要不要自定义”这两个维度上做选择,凭据配置这一层的原理是完全一致的。

个人开发者的私有模块拉取

直接使用 GitHub / GitLab 等平台的私有仓库

这是最简单、成本最低的场景。假设你在 GitHub 上有一个私有仓库 github.com/tonybai/privatemodule,配置如下:

export GOPRIVATE=github.com/tonybai/*
git config --global url."https://oauth2:${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"

go get github.com/tonybai/privatemodule 即可正常工作,go.mod 里的 module path 直接就是 github.com/tonybai/privatemodule,不需要任何额外的“翻译层”。

想用个人域名做 import path,代码仍托管在 GitHub / GitLab / Codeberg 等平台

如果你不满足于 github.com/tonybai/privatemodule 这种带着托管平台印记的 import path,希望换成 example.me/go/privatemodule,或者希望以后即便把仓库从 GitHub 挪到 GitLab、Codeberg,import path 也保持不变,这就需要引入 vanity import URL 机制。

原理很简单:Go 工具链请求 https://example.me/go/privatemodule?go-get=1 时,期望拿到一个包含 go-import meta 标签的 HTML 页面,告诉它真实仓库地址在哪里:

<meta name="go-import" content="example.me/go/privatemodule git https://github.com/tonybai/privatemodule">

按运维成本从低到高,有几种落地方式:

方案一:手写静态 HTML,挂到 GitHub Pages / Cloudflare Pages 上

几乎零成本,只要给每个 module 路径建一个静态页面即可,缺点是每新增一个 module 都要手动加一个页面,仓库多了之后维护起来比较琐碎。

方案二:自己部署 govanityurls

govanityurls 是官方 golang.org/x 下的一个开源工具,读取一份 YAML 映射配置,自动生成对应的 go-import 页面。需要自己找一台机器(哪怕是最便宜的 VPS)跑这个服务,前面配一层 Nginx 做 TLS 终止。可控性最高,但要自己维护这套服务的可用性和证书续期。

方案三:用 gvu 这类托管服务

如果不想自己运维一套 govanityurls + Nginx,也可以用 gvu(gomodvanityurls.com)这类托管化的 vanity URL 服务,一条命令创建映射:

gvu add example.me/go/privatemodule https://github.com/tonybai/privatemodule.git

不需要自己起服务、配证书,适合不想为了一个 vanity 层单独维护基础设施的个人开发者。这只是三种方案里的一种,具体选哪种,取决于你是否愿意为了完全的可控性,多维护一套自己的服务。

自己在 VPS 上搭 Git Server,同时想用个人域名做 import path

如果你更进一步,连代码托管也不想依赖第三方平台,自己在 VPS 上跑了 Gitea、GitLab CE 或者 Codeberg 式的自建 Git Server,这里有个关键认知:vanity 解析层和实际代码托管,完全可以是两个互相独立的服务,用的甚至可以是不同的域名、不同的机器。

这种场景下,前面三种方案依然都成立,只是 go-import 里指向的真实仓库地址,从 github.com/... 换成了你自己 VPS 上的 Git Server 地址,例如:

<meta name="go-import" content="example.me/go/privatemodule git https://git.example.me/tonybai/privatemodule">

对应到 gvu 的用法上,就是把目标仓库地址换成你自建 Git Server 的地址:

gvu add example.me/go/privatemodule https://git.example.me/tonybai/privatemodule.git

同样,手写静态页面或者自建 govanityurls 这两种方式在这个场景下也完全适用,选择哪种取决于你愿意为“完全自主可控”付出多少运维成本。

组织 / 团队的私有模块拉取

组织场景相比个人场景,多出的核心考量是:仓库数量更多、参与人员更多、可用性要求更高——vanity 解析服务一旦故障,可能意味着全公司的 CI 流水线都构建失败,这是个人场景基本不需要考虑的风险等级。

组织统一使用 GitHub / GitLab 等平台的私有仓库

这是最常见的组织场景,凭据管理上比个人场景多几个需要注意的点:

  • 建议用机器账号(bot account)而不是某个具体成员的个人账号去生成访问令牌,避免因为人员变动导致 CI 突然失效;
  • 令牌尽量按仓库或按项目限权,而不是签发一个能访问组织下所有仓库的超级令牌;
  • 令牌统一放在 CI 平台的 secret 管理里,避免散落在各个项目的配置文件中。

其余配置和个人场景完全一致,GOPRIVATE 换成组织域名前缀即可:

export GOPRIVATE=github.com/mycorp/*

组织想用组织域名做 vanity import path

这是很多团队迟早会遇到的需求:不希望 go.mod 里到处是 github.com/mycorp/xxx,而是想统一成 go.mycompany.com/xxx,一方面是品牌语义,另一方面是为未来可能的仓库迁移(比如从 GitHub 换到自建 GitLab)留出余地——只要 vanity 层的映射改一下,所有下游使用方的 import path 完全不用变。

五年前我在公司内部第一次搭建这类方案时,写过几篇实践记录(《小厂内部私有Go module拉取方案》、《小厂内部私有Go module拉取方案(续)》和《小厂内部私有Go module拉取方案3》),走的就是自建 govanityurls + Nginx 这条路。这套方案跑了五年,整体稳定,最大的优势是完全自主可控,不依赖任何第三方服务;代价是每新增一个仓库都要手动改一次映射配置、重载一次 Nginx,团队规模大了之后,这个日常维护成本会逐渐显现出来。

如果团队不想自己承担这部分运维成本,用 gvu 这类托管方案可以把“新增映射”这个动作压缩成一条命令,而且天然具备高可用(不用担心自己那台跑 govanityurls 的机器挂了导致全公司构建失败):

gvu add go.mycompany.com/privatemodule https://github.com/mycorp/privatemodule.git

两种路线各有取舍:

  • 自建方案胜在完全自主、不依赖外部服务的可用性;
  • 托管方案胜在免运维、天然高可用。

具体选哪个,取决于团队愿意在这件事上投入多少运维精力。

组织在内部数据中心 / VPS 自建 Git Server,同时要 vanity import path

这是组织场景里最复杂、也最容易被低估的一种情况:私有代码托管在内部数据中心自建的 GitLab / Gitea 上,同时又希望有一层语义化的 vanity import path。原理和 前面个人场景自建git server完全一致,只是仓库地址换成了内部数据中心的地址(通常是内网 IP 或内网域名)。

这里额外提一句:如果你的团队还涉及把这类私有代码以“白盒交付”的方式给到外部客户,会遇到一个更棘手的问题——客户的网络环境访问不到你内部的 vanity 服务和内部仓库,这又是另一套需要专门讨论的方案了,我在上一篇《五年,三篇文章,一个我一直没真正解决的问题》里记录过我的具体做法,这里不展开。

小结:怎么选

把上面讨论的几个维度整理成一份简单的参考:

  • 只是想让私有依赖能被 go get 拉到,不在乎 import path 好不好看:直接用托管平台的私有仓库 + 对应凭据配置即可,不需要引入 vanity 层。
  • 想要自定义 import path,且不介意自己运维一套服务:手写静态页面(仓库少)或自建 govanityurls(仓库多、要求可控)都是合理选择。
  • 想要自定义 import path,但不想自己运维 vanity 服务:可以看看 gvu gomodvanityurls.com这类托管方案,一条命令搞定映射。
  • 组织规模较大、涉及高可用要求,或者需要频繁给不同客户 / 项目分配独立的 import path:优先考虑免运维的托管方案,或者在自建方案上补齐高可用保障,两者都是可行路径,关键是提前想清楚团队愿意为“完全自主可控”付出多少运维成本。

无论最终选哪条路,先把第一部分那几个环境变量的职责边界搞清楚,后面遇到的大多数报错,基本都能顺着这条线索排查出来。


还在为写 Agent 框架频频死循环、上下文爆炸而束手无策?我的新专栏 从0 开始构建 Agent Harness 将带你:

  • 抛弃臃肿框架,回归“驾驭工程 (Harness Engineering)”的第一性原理
  • 用 Go 语言手写 ReAct 循环、并发拦截与上下文压缩引擎等,复刻极简OpenClaw
  • 构建坚不可摧的 Safety Middleware 与飞书人工审批防线
  • 在底层实现 Token 成本审计、链路追踪与自动化跑分评估
  • 从“调包侠”进化为掌控大模型边界的“AI 操作系统架构师”

扫描下方二维码,开启从 0 开始构建Agent Harness 的实战之旅。


你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?

  • 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
  • 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
  • 想打造生产级的Go服务,却在工程化实践中屡屡受挫?

继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!

我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。

目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。