路由税
你的团队已经用上了 vanity URL。导入路径干净了,不再绑定平台,看着就舒服:
import "go.mycorp.com/auth"
import "go.mycorp.com/config"
import "go.mycorp.com/logger"
然后团队扩张了。每个迭代都有新服务上线。每个新服务都需要一条 gvu add 命令:
gvu add go.mycorp.com/auth https://github.com/mycorp/auth.git
gvu add go.mycorp.com/config https://github.com/mycorp/config.git
gvu add go.mycorp.com/logger https://github.com/mycorp/logger.git
gvu add go.mycorp.com/cache https://github.com/mycorp/cache.git
gvu add go.mycorp.com/queue https://github.com/mycorp/queue.git
# ... 还有 45 个
50 个仓库,50 条路由。每新建一个仓库就要提个 PR 更新路由配置。谁忘了?新服务的 go get 直接报错,整个团队被卡住。
这就是路由税——维护 vanity URL 映射的人工开销,而这些映射本该是自动的。
一条规则覆盖所有仓库
通配路由消灭路由税。不需要逐个添加仓库,你只需要写一条规则覆盖路径前缀下的所有仓库:
gvu add 'go.mycorp.com/*' 'https://github.com/mycorp/*.git'
搞定。一行命令。现在 mycorp GitHub org 下的每个仓库都自动可用 vanity 路径导入:
import "go.mycorp.com/auth" // → github.com/mycorp/auth
import "go.mycorp.com/config" // → github.com/mycorp/config
import "go.mycorp.com/logger" // → github.com/mycorp/logger
import "go.mycorp.com/newthing" // → github.com/mycorp/newthing(立刻可用!)
在 GitHub 上创建了个新仓库?立刻可以用 vanity 域名 go get 拉取。不用改配置,不用提 PR,不用等人。
这是 Repo 通配(W1)——vanity path 中的 * 匹配任意单个路径段,repo URL 中的 * 被匹配到的名称替换。
Monorepo?用 Subdir 通配
如果你的模块在 monorepo 里,而不是独立仓库呢?
monorepo/
├── go/
│ ├── auth/go.mod
│ ├── config/go.mod
│ ├── logger/go.mod
│ ├── cache/go.mod
│ └── ... 还有 20 个
你不需要 repo 通配。你需要的是 Subdir 通配(W2):
gvu add go.mycorp.com/libs https://github.com/mycorp/monorepo.git '--subdir=*'
monorepo 中任意子目录下的 Go 模块都自动可导入:
import "go.mycorp.com/libs/auth" // → monorepo,subdir go/auth
import "go.mycorp.com/libs/config" // → monorepo,subdir go/config
import "go.mycorp.com/libs/cache" // → monorepo,subdir go/cache
往 monorepo 里加新模块?自动可导入——不需要改任何路由。
注意:Subdir 通配需要每个模块的
go.mod声明 Go 1.25+。完整配置参见我们的 monorepo 教程。
实战场景
场景 1:多团队组织
公司有三个团队,各有独立的 GitHub org:
# 平台团队 — 15 个仓库
gvu add 'go.mycorp.com/platform/*' 'https://github.com/mycorp-platform/*.git'
# 数据团队 — 12 个仓库
gvu add 'go.mycorp.com/data/*' 'https://github.com/mycorp-data/*.git'
# 基础设施团队 — monorepo 里的 8 个模块
gvu add go.mycorp.com/infra https://github.com/mycorp-infra/monorepo.git '--subdir=*'
三条规则。三十五个模块。零维护。
场景 2:覆盖特定仓库
有些仓库不符合通配规则。可能它在另一个 org 里,或者它是一个 fork。用精确路由覆盖:
# 通配规则覆盖大部分仓库
gvu add 'go.mycorp.com/*' 'https://github.com/mycorp/*.git'
# 但 auth 已经迁到了另一个 org
gvu add go.mycorp.com/auth https://github.com/security-team/auth.git
# logger 是一个维护中的 fork
gvu add go.mycorp.com/logger https://github.com/upstream/logger.git
gvu 通过优先级规则解决冲突:
| 优先级 | 规则类型 | 匹配场景 |
|---|---|---|
| 1(最高) | 精确路由 | 特定仓库的覆盖 |
| 2 | Subdir 通配(W2) | Monorepo 子包 |
| 3(最低) | Repo 通配(W1) | org 级别的兜底 |
精确路由永远优先于通配。这让你可以用宽泛的默认规则加上精准的例外。
场景 3:渐进式采用
不想一步到位?先用精确路由管理最常用的模块,路由数量多了再加通配:
# 第 1 周:就几个模块
gvu add go.mycorp.com/auth https://github.com/mycorp/auth.git
gvu add go.mycorp.com/config https://github.com/mycorp/config.git
# 第 5 周:太多了,管不过来了
gvu add 'go.mycorp.com/*' 'https://github.com/mycorp/*.git'
# 精确路由仍然有效——它们优先级更高
底层原理
当开发者运行 go get go.mycorp.com/auth 时,Go 工具链向 https://go.mycorp.com/auth?go-get=1 发送请求。gvu 的服务器:
- 先查精确路由——有没有
go.mycorp.com/auth的精确规则? - 再查 Subdir 通配(W2)——有没有 W2 规则的前缀匹配?
- 最后查 Repo 通配(W1)——有没有 W1 规则的模式匹配?
当通配命中时,服务器动态生成 go-import meta 标签:
<!-- W1 匹配:go.mycorp.com/auth → github.com/mycorp/auth -->
<meta name="go-import" content="go.mycorp.com/auth git https://github.com/mycorp/auth">
<!-- W2 匹配:go.mycorp.com/libs/auth → github.com/mycorp/mono subdir go/auth -->
<meta name="go-import" content="go.mycorp.com/libs/auth git https://github.com/mycorp/mono go/auth">
没有静态 HTML 文件。没有 Nginx 配置。meta 标签从通配规则动态生成。
前提条件
通配路由是 Pro 功能。你需要:
| 条件 | 说明 |
|---|---|
| Pro 账户 | 运行 gvu subscribe — 50 条路由、自定义域名、通配 |
| 自定义域名 | go.mycorp.com DNS CNAME 指向 gvu |
不支持 gomod.io | 通配需要你自己的域名 |
为什么不支持 gomod.io?因为 gomod.io 下的通配会让任何人声明该域名下的任意路径,存在安全风险。
配置自定义域名
# 1. 添加 CNAME 记录
go.mycorp.com CNAME gomodvanityurls.com
# 2. 用 gvu 验证
gvu domain add go.mycorp.com
gvu domain verify go.mycorp.com
# 3. 创建通配路由
gvu add 'go.mycorp.com/*' 'https://github.com/mycorp/*.git'
HTTPS 证书自动签发——不需要手动管理证书。
限制与注意事项
几点需要记住:
- 每条规则只能有一个
*——不能写go.mycorp.com/*/*(路径中两个通配符) - W1 和 W2 互斥——同一条路由只能用 repo 通配或 subdir 通配,不能同时使用
- 每条通配路由占 1 个 Pro 配额(共 50 个)
- Shell 引号很重要——包含
*的参数必须用单引号包裹:
# ✅ 正确
gvu add 'go.mycorp.com/*' 'https://github.com/mycorp/*.git'
# ❌ 错误——shell 会展开 glob
gvu add go.mycorp.com/* https://github.com/mycorp/*.git
前后对比
| 维度 | 逐个添加路由 | 通配路由 |
|---|---|---|
| 配置 | 每个模块一条命令 | 每个 org/monorepo 一条命令 |
| 新建仓库 | 必须先加路由 | 立即可用 |
| 路由数量 | N 个仓库 = N 条路由 | N 个 org = N 条规则 |
| 维护成本 | 每次新服务都要更新 | 设一次,永久生效 |
| 例外处理 | 不适用 | 精确路由优先覆盖 |
总结
如果你有超过 5 个 Go 模块,通配路由立刻能回本:
# 多仓库 org:一条规则覆盖全部
gvu add 'go.mycorp.com/*' 'https://github.com/mycorp/*.git'
# Monorepo:一条规则覆盖所有子包
gvu add go.mycorp.com/libs https://github.com/mycorp/mono.git '--subdir=*'
# 混合使用精确覆盖
gvu add go.mycorp.com/special https://github.com/other/special.git
每个 org 一条规则。每个 monorepo 一条规则。精确路由处理例外。这就是一个 50 模块组织的完整路由配置。
升级到 Pro,5 分钟内配好通配路由。