- 文档
- 教程
- 云原生
【免费下载链接】docs
User documentation for Knative components.
本文围绕 Knative 文档仓库中的 tools/redir-gen 工具展开,讲解它如何自动重生成golang/目录下的重定向规则与go-import元数据页面,使knative.dev/<repo>这样的 Go 模块路径可被go get、go doc正确解析。读完本文,你将掌握该工具的运行方式、源码级实现原理、生成产物的结构与含义,以及它在站点构建(hack/build.sh)中的部署位置。
一、工具定位:redir-gen 解决什么问题
Go 语言对形如knative.dev/serving的自定义域名模块路径,要求托管方提供一个“vanity import path”解析机制:当go get knative.dev/serving发起请求时,Go 工具链会向https://knative.dev/serving?go-get=1发送请求,服务器需返回包含<meta name="go-import">标签的 HTML 页面,将模块路径映射到真实的代码托管仓库(如 GitHub),go-source标签则用于go doc等工具定位源码位置。
docs 仓库正是通过 tools/redir-gen 这个小工具来维护这套机制。关联文档对它的定位只有一句话,但非常清晰:
This tool regenerates the redirects in the
golang/folder.
也就是说,仓库根目录下的 golang/ 目录不是手写的,而是由该工具自动生成的:目录中每个.html文件对应一个仓库的go-import/go-source元数据页,_redirects文件则记录站点层面的重定向规则。任何对该目录的手动修改都会在下次重新生成时被覆盖。
二、快速开始:一条命令重新生成
按关联文档说明,在仓库根目录执行:
go run ./tools/redir-gen/运行前置条件如下(均可在仓库中确认):
| 前置条件 | 说明 | 仓库依据 |
|---|---|---|
| Go 工具链 | 项目声明go 1.24.0 | go.mod |
| 依赖 go-github | 通过 GitHub REST API 拉取仓库列表 | go.mod:github.com/google/go-github/v32 v32.1.0 |
| 网络访问 | 需要访问 GitHub API;未配置认证的客户端受匿名速率限制 | 源码中github.NewClient(nil)未注入 Token(main.go) |
| 必须位于根目录 | 产物路径golang/与golang/_redirects均为相对当前目录的路径 | main.go、main.go |
执行完成后会产生两类输出:
golang/<repo>.html:为每个仓库生成一个 HTML 元数据页(共 72 个);golang/_redirects:整文件重写(O_TRUNC模式打开),先写入 AUTO-GENERATED 头注释,再写入每个仓库的重定向规则(共 70 条,含 3 条 pkg.go.dev 跳转)。
_redirects文件头部明确提示了不可手改:
# This file is AUTO-GENERATED # # DO NOT EDIT! # # To regenerate, run: # go run ./tools/redir-gen/这段头注释由源码中的autogenPrefix常量写入(main.go)。
三、源码级拆解:redir-gen 的完整工作流程
main.go 共约 219 行,main()的流程非常紧凑(main.go):先fetchRepos拉取并过滤仓库列表,再对每个仓库执行createGoGetFile生成 HTML,最后appendRedirs重写_redirects。下面按步骤拆解。
3.1 仓库枚举与过滤(fetchRepos)
fetchRepos(main.go)负责从 GitHub 拉取仓库列表,核心逻辑:
- 扫描两个组织:
knative与knative-extensions(main.go)。从产物可验证这一行为——例如 func-go.html 中go-import指向的是github.com/knative-extensions/func-go,而 serving.html 指向github.com/knative/serving。 - 分页抓取:每页 50 个仓库,循环直到
resp.NextPage == 0(main.go)。 - 名称白名单正则:
allowedRepoRe = ^[a-z][-a-z0-9]+$,不匹配的仓库直接跳过并打印日志(main.go、main.go)。 - 归档仓库排除:已归档(
Archived == true)的仓库默认跳过,但eventing-contrib、control-protocol两个仓库作为例外仍会保留(archivedExceptions,main.go)。 - 排序:全部收集完成后按
Repo名升序排序(main.go),这解释了_redirects中规则大致按字母序排列的现象。
一个从源码结构值得注意的细节:代码顶部定义了ignoreRepos列表(含actions、community、docs、knobots、monitoring、release,见 main.go),但当前并没有任何函数引用它——实际过滤只使用allowedRepoRe与归档判断。从生成结果看,_redirects中确实仍存在/actions/*、/community/*、/docs/*、/knobots/*、/monitoring/*、/release/*等规则,与“ignoreRepos 未生效”的代码观察一致。可以推断这是一个定义在先、尚未接入过滤逻辑的预留配置。
3.2 repoInfo 结构与 Module 覆盖
每个仓库被封装为repoInfo结构体(main.go),包含四个字段:
| 字段 | 含义 | 示例 |
|---|---|---|
Org | 所在 GitHub 组织 | knative/knative-extensions |
Repo | 仓库名(不含组织前缀) | serving |
Module | 对外暴露的 Go 模块名 | 默认等于Repo,可被repoToModule覆盖 |
DefaultBranch | 仓库默认分支 | main |
repoToModule映射提供了模块名覆盖机制(main.go),当前仅有一条func-go: func-go。它说明:即便仓库在组织内叫func-go,也可以显式指定其对外模块名——目前二者一致,但机制本身是开放的,未来仓库改名时无需改动生成逻辑,只需调整映射。
3.3 生成 go-import HTML(createGoGetFile)
createGoGetFile(main.go)为每个仓库在golang/<repo>.html中写入goHTML模板渲染结果:
<html><head> <meta name="go-import" content="knative.dev/{{.Module}} git https://github.com/{{.Org}}/{{.Repo}}"> <meta name="go-source" content="knative.dev/{{.Module}} https://github.com/{{.Org}}/{{.Repo}} https://github.com/{{.Org}}/{{.Repo}}/tree/{{.DefaultBranch}}{/dir} https://github.com/{{.Org}}/{{.Repo}}/blob/{{.DefaultBranch}}{/dir}/{file}#L{line}"> </head></html>(模板原文见 main.go。)
两个 meta 标签的分工:
go-import:告诉 Go 工具链“knative.dev/<module>的代码托管在哪个 git 仓库”,是go get解析的关键;go-source:提供源码浏览入口(仓库主页、按目录的 tree 路径、按文件的行级 blob 链接),供go doc等工具使用。
模板中{/dir}、{file}、{line}是 go-source 约定的占位符,会被 Go 工具链替换为实际请求路径。DefaultBranch字段会被注入到 tree/blob 链接中——源码注释提到默认分支正从master向main迁移(main.go),从现有产物看均已是main,例如 serving.html。
3.4 生成 _redirects(appendRedirs)
appendRedirs(main.go)以截断写模式打开golang/_redirects,先写入autogenPrefix,再为每个仓库写入两条模板中的一条或两条:
/{{.Repo}}/* go-get=:go-get /golang/{{.Repo}}.html 200 /{{.Repo}}/* https://pkg.go.dev/knative.dev/{{.Repo}}/:splat(模板见 main.go。)
第一条是核心规则,语法含义为:当站点收到knative.dev/<repo>/...且携带?go-get=1参数(go-get=:go-get即“请求带 go-get 参数时命中”)时,返回 200 并转发到/golang/<repo>.html。这正是第一节所述 vanity import 解析的服务器端实现,且与 Go 工具链的无参浏览器访问(返回 200 的静态页,无跳转)相兼容。
第二条仅对已知包含 Go 库的仓库追加(isGoRepo判断,名单为pkg、serving、security-guard,见 main.go、main.go):浏览器访问knative.dev/pkg/xxx时直接 301 到https://pkg.go.dev/knative.dev/pkg/xxx(:splat保留原路径后缀)。源码注释对该行为的解释是“这些仓库已知包含 Go 库,浏览器访问应跳转到 pkg.go.dev 的包文档”(main.go)。对应产物如 golang/_redirects 中的:
/pkg/* go-get=:go-get /golang/pkg.html 200 /pkg/* https://pkg.go.dev/knative.dev/pkg/:splat四、产物解读:golang/ 目录里有什么
目录内包含三类文件,均以 golang/README.md 中的声明为准:“This Directory is AUTO-GENERATED. Do not modify directly, run ./tools/redir-gen.”
| 产物 | 数量 | 说明 |
|---|---|---|
golang/*.html | 72 个 | 每个仓库一个 go-import/go-source 元数据页 |
golang/_redirects | 70 条规则 | 67 条go-get=:go-get规则 + 3 条pkg.go.dev跳转(pkg、serving、security-guard) |
golang/README.md | 1 个 | AUTO-GENERATED 声明,提示运行方式 |
从目录内容与_redirects对照可以观察到一个现象:存在async-component.html、container-freezer.html、kperf.html、scaling-group.html等 HTML 文件,但_redirects中没有对应的重定向规则。这与源码结构吻合——createGoGetFile只会创建文件、从不清理旧文件(main.go),可以推断这些是历史运行遗留的陈旧产物(对应仓库可能已被归档或从名单中移除)。这是生成器“只增不删”行为带来的典型维护注意点。
五、构建与部署集成:产物如何上线
golang/产物最终通过 hack/build.sh 进入发布站点:
# Copy go mod files so knative.dev/blahblah vanity URLs work mkdir site/golang cp golang/*.html site/golang/ cat golang/_redirects >> site/_redirects即:把全部 HTML 元数据页拷贝到站点golang/目录,再把_redirects追加到站点根级_redirects中,使knative.dev/<repo>的 vanity URL 在部署后即可工作。构建脚本的注释也直接点明了目的:“so knative.dev/blahblah vanity URLs work”。
需要区分的是,仓库中还存在另外两套重定向机制,职责不同:
- config/redirects.yml:由 MkDocs redirects 插件消费的文档内链接映射(如
versioned/contributing/about.md -> community/contributing.md),负责文档页面级别的 301 迁移; - netlify.toml:Netlify 平台层面的站点级重定向(如
/contributing/→/community/contributing/),属人工维护的静态规则; golang/_redirects:由 redir-gen 自动生成的 go-get 解析规则,属于工具产物。
三者的共同点是最终都会汇聚到站点部署层的重定向处理,但只有golang/_redirects是机器生成的、必须通过工具再生的。
六、验证与维护建议
验证生成结果是否生效,可用 curl 模拟go get的请求方式,检查返回的 HTML 是否包含正确的go-import元数据:
curl -s "https://knative.dev/serving?go-get=1" | grep go-import # 应输出类似:<meta name="go-import" content="knative.dev/serving git https://github.com/knative/serving">以下场景出现时,应当重新在仓库根目录运行go run ./tools/redir-gen/:
- 新增或移除
knative/knative-extensions组织下的仓库; - 某仓库被归档(默认会被自动排除,除非加入
archivedExceptions); - 仓库默认分支变更(模板会随之更新 tree/blob 链接);
- 需要调整
redirectingGoRepos(pkg.go.dev 跳转名单)或repoToModule(模块名覆盖)。
综上,redir-gen 是一个典型的“元数据即产物”代码生成器:它把 Go vanity import 的解析规则、GitHub 仓库清单与站点重定向统一收敛为可再生的产物,避免了人工维护golang/目录时的错漏,是 docs 仓库在模块化文档体系下保持knative.dev/*路径长期可用性的基础设施。
- 文档
- 教程
- 云原生
【免费下载链接】docs
User documentation for Knative components.
相关推荐
GORM代码生成:Gen工具的使用与自定义
GORM代码生成:Gen工具的使用与自定义 GORM Gen是Golang生态中功能强大的数据库代码生成工具,它能够根据数据库表结构自动生成类型安全的ORM代码
后端数据库ORMGo 代码生成工具 gen 使用教程
Go 代码生成工具 gen 使用教程 1. 项目介绍 gen 是一个为 Go 语言设计的代码生成工具,旨在提供类似泛型的功能。它提供了 LINQ/undersc
开发工具wewe-rss 完整指南:如何在 15 分钟内把微信公众号变成标准 RSS 订阅源
wewe rss 完整指南:如何在 15 分钟内把微信公众号变成标准 RSS 订阅源 你的订阅号列表红点 99+,真正想看的那篇文章早被刷到第三条。wewe r
后端前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考