Hugo 模板函数 collections.Querify 完全指南:从键值对到 URL 查询字符串
【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo
导读
collections.Querify是 Hugo 模板引擎中负责把键值对数据(map、slice 或标量序列)编码为 URL 查询字符串(query string)的函数,广泛应用于构建带参数的链接、嵌入第三方内容(如 YouTube、Vimeo、X 等 shortcode)以及处理站点配置或 front matter 中的参数。阅读本文后,你将掌握 Querify 的三种输入形态、编码与排序规则、错误边界,以及它在真实项目中的调用方式与源码实现细节。
函数签名与基本用法
根据官方文档 Querify.md 的定义,该函数返回类型为string,签名如下:
collections.Querify MAP|SLICE|KEY VALUE...即接受三种等价的数据形态:
- 一个 map(由
dict创建,或来自项目配置、页面 front matter) - 一个 slice(键值交替排列,偶数个元素)
- 一段标量序列(键、值逐个传入,同样必须为偶数个)
文档给出的三行等价示例:
{{ collections.Querify (dict "a" 1 "b" 2) }} {{ collections.Querify (slice "a" 1 "b" 2) }} {{ collections.Querify "a" 1 "b" 2 }}三者输出完全相同:a=1&b=2。
在模板中还可以省略命名空间前缀,直接写作querify——该别名在 tpl/collections/init.go 中通过ns.AddMethodMapping(ctx.Querify, []string{"querify"}, ...)注册。
向 URL 追加查询字符串
最常见的实战场景是把查询字符串拼接到链接上。官方文档给出的完整示例:
{{ $qs := collections.Querify (dict "a" 1 "b" 2) }} {{ $href := printf "https://example.org?%s" $qs }} <a href="{{ $href }}">Link</a>Hugo 渲染结果为:
<a href="https://example.org?a=1&b=2">Link</a>注意渲染结果中&被转义为&,这是 HTML 输出的标准转义行为,浏览器解析后实际跳转地址仍是https://example.org?a=1&b=2。若你需要在无需 HTML 转义的场景(例如生成 sitemap 或 JavaScript 配置)中直接使用,可结合safeHTML/safeURL管道处理,这在下文源码示例中会进一步说明。
传入配置与 front matter 中的 map
Querify 不仅支持模板内用dict临时构造的 map,也直接支持项目配置或页面 front matter 中定义的 map。文档示例在 front matter 中定义了一个params.query参数:
title = 'Example' [params.query] a = 1 b = 2随后在模板中通过页面参数对象取出该 map 并传给 Querify:
{{ collections.Querify .Params.query }}输出同样为a=1&b=2。这意味着你可以在配置中心维护一套"默认查询参数",然后在多个模板中复用,避免在模板里硬编码参数。
编码、排序与格式规则
Querify 的输出遵循application/x-www-form-urlencoded规范,其底层实现位于 tpl/collections/querify.go,核心逻辑:
- 使用 Go 标准库
net/url.Values累积键值对,最终调用qs.Encode()输出; - 按 key 排序输出,保证结果确定、可预期(
Encode()会按键名排序); - 值统一通过
cast.ToStringE转换为字符串,因此数字(如1、7)会被序列化为a=1&b=7; - 特殊字符会被 URL 编码:空格编码为
+,&、=、%等保留字符编码为%XX形式。
tpl/collections/init.go 中注册的官方示例直观展示了编码效果:
{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}输出:
bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose可以看到:键baz的值with spaces中的空格被编码为+;键qux的值this&that=those中的&与=被分别编码为%26与%3D,且输出严格按bar、baz、foo、qux的字典序排列。
init.go 中的另一个示例展示了拼接外部搜索 URL 的完整用法:
<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>渲染为:
<a href="https://www.google.com?page=3&q=test">Search</a>源码实现与输入形态的分派逻辑
从源码结构看,Querify 的分派逻辑可以概括为:
- 零参数:直接返回空字符串
"",不报错; - 单参数:按类型分派——
map[string]any(dict创建的 map)→mapToQueryStringhmaps.Params(项目配置或页面参数)→mapToQueryString[]string/[]any(slice)→ 转为字符串 slice 后走stringSliceToQueryString- 其他类型 → 返回
errWrongArgStructure
- 多参数:要求个数为偶数,否则返回错误;全部元素先经
cast.ToStringE转为字符串,再两两配对。
其中对hmaps.Params的专门支持(见 tpl/collections/querify.go)正是上文"直接传入.Params.query这类配置 map"能够成立的根本原因——Hugo 的配置与页面参数在内部正是以hmaps.Params类型存储的。
错误边界与约束
结合 querify.go 中定义的两个错误变量,以及 querify_test.go 中覆盖的 27 组测试用例,Querify 有以下明确约束:
| 场景 | 行为 |
|---|---|
| 无参数 | 返回空字符串,无错误 |
| 空 map / 空 slice | 返回空字符串,无错误 |
键或值为""(空字符串键) | 返回one of the keys is an empty string错误 |
| 元素个数为奇数(无法配对) | 返回expected a map, a slice with an even number of elements, or an even number of scalar values, and each key must be a string错误 |
值无法转换为字符串(如无String()方法的任意类型) | 返回cast.ToStringE的转换错误 |
在模板中使用时,若传入数据可能不符合上述约束(例如来自用户可控的 front matter),建议先用with或条件判断包裹,避免渲染阶段直接报错。
内置 shortcode 中的真实调用
Querify 并不是孤立存在的模板函数,它已经被 Hugo 的内置嵌入模板广泛使用,可作为最佳实践参照:
- youtube.html:将 autoplay、controls、end、mute、start、loop 等播放参数放入
dict,querify $params生成 iframe 的src查询串; - vimeo_simple.html:
querify "url" $url "dnt" $dnt以标量序列形态构建参数; - x_simple.html:
querify "url" $url "dnt" $dnt "omit_script" true混合了字符串与布尔值,布尔值会被cast为字符串true。
这些内置模板恰好覆盖了本文介绍的三种输入形态(map、slice 序列),也印证了 Querify 在 Hugo 渲染管线中是构建合规查询串的标准工具。
性能与实战建议
querify_test.go 中还提供了三组基准测试(BenchmarkQuerify、BenchmarkQuerifySlice、BenchmarkQuerifyMap),分别覆盖标量序列、字符串 slice 与 map 三种输入路径,说明该函数设计上就考虑到在每次页面渲染中可能被高频调用的场景,可放心在循环或 shortcode 内部使用。
实战建议总结:
- 优先使用
dict或配置 map:语义清晰,且可直接复用.[params]中定义的默认参数; - 注意 HTML 转义:拼接进
<a href>时&会被渲染为&,属正常现象;如需原始输出可组合safeHTML/safeURL; - 保证键非空、元素个数为偶数:避免触发文档与测试中定义的错误分支;
- 善用"配置驱动"模式:把查询参数收敛到站点配置中,配合 Querify 统一生成链接,便于多语言、多页面场景下集中维护。
参考文件
- 官方函数文档:docs/content/en/functions/collections/Querify.md
- 核心实现:tpl/collections/querify.go
- 测试与基准:tpl/collections/querify_test.go
- 别名注册与官方示例:tpl/collections/init.go
- 内置 shortcode 使用示例:youtube.html、vimeo_simple.html、x_simple.html
【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考