news 2026/9/18 17:58:53

Hugo 模板函数 collections.Sort 完全指南:对切片、Map 与页面集合进行排序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Hugo 模板函数 collections.Sort 完全指南:对切片、Map 与页面集合进行排序

Hugo 模板函数 collections.Sort 完全指南:对切片、Map 与页面集合进行排序

【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo

collections.Sort(模板别名sort)是 Hugo 模板中最常用的集合处理函数之一,它接收一个切片(slice)或映射(map),按指定的键(KEY)与顺序(ORDER)返回一份已排序的副本。本文以官方函数文档为主体,结合仓库源码(tpl/collections/sort.go)与测试用例,系统讲解sort的三种典型用法——排序切片、排序 Map、排序页面集合,并深入其底层实现原理,帮助你写出可靠、可维护的排序模板。

函数签名与参数

根据官方文档(见 docs/content/en/functions/collections/Sort.md),sort的完整签名为:

collections.Sort MAP|SLICE [KEY] [ORDER]

函数别名注册在 tpl/collections/init.go#L184-L187,模板中可以直接写sort。其参数规则如下:

参数说明默认值 / 约束
第一个参数待排序的集合,必须是map 或 slice必填;传入nil或其它类型会报错
KEY排序依据的字段名排序切片且升序时可省略,其余情况必填;排序切片时用字面量value表示元素本身
ORDER排序方向asc(升序)或desc(降序),默认升序

返回类型为any(排序后的切片或 Map 值集合)。源码 tpl/collections/sort.go#L44-L51 显示,函数仅接受reflect.Arrayreflect.Slicereflect.Map三种类型,遇到其它类型会返回can't sort ...错误;对nil值则分别返回sequence must be providedcan't iterate over a nil value错误。

排序切片

以下示例假定站点配置(hugo.toml)中包含:

[params] grades = ['b','a','c']

升序排列

排序切片元素时,KEY可以省略(仅限升序),也可以显式传入字面量value

{{ sort site.Params.grades }} → [a b c] {{ sort site.Params.grades "value" "asc" }} → [a b c]

两种写法等价。这里value即切片元素自身的占位键。此规则同样适用于其它基础类型切片,例如init.go中的示例{{ slice "B" "C" "A" | sort }}输出[A B C]

降序排列

排序切片元素时,ORDERdesc则必须同时提供KEY

{{ sort site.Params.grades "value" "desc" }} → [c b a]

从源码 tpl/collections/sort.go#L75-L100 可以看到,当sortByField为空或等于"value"时,pairList直接以元素值本身作为排序键;否则会沿KEY指定的路径逐层求值。sort_test.go中亦有对应断言,如{[]string{"class3", "class1", "class2"}, "value", "desc", []string{"class3", "class2", "class1"}}(见 tpl/collections/sort_test.go#L89-L90)。

对结构体 / Map 元素按字段排序

当切片元素是结构体或 Map 时,KEY指定其内部字段名。例如按结构体的字符串字段、整数字段或浮点字段排序,测试用例均给出了验证(见 tpl/collections/sort_test.go#L69-L87)。KEY还支持**点链式(dot chaining)**写法,深入嵌套层级,例如"foo.A""foo.Tst.A"分别取foo下的A字段、foo.Tst下的A字段(见 tpl/collections/sort_test.go#L131-L204)。对应源码在 tpl/collections/sort.go#L73 处将KEY.分割为路径逐级求值。

排序 Map

以下示例假定站点配置中包含:

[params.authors.a] firstName = 'Marius' lastName = 'Pontmercy' [params.authors.b] firstName = 'Victor' lastName = 'Hugo' [params.authors.c] firstName = 'Jean' lastName = 'Valjean'

[!NOTE] 排序 Map 时,KEY参数必须小写

升序排列

firstName字段升序排列 Map 对象:

{{ range sort site.Params.authors "firstname" }} {{ .firstName }} {{ end }} {{ range sort site.Params.authors "firstname" "asc" }} {{ .firstName }} {{ end }}

两种写法均输出:

Jean Marius Victor

降序排列

{{ range sort site.Params.authors "firstname" "desc" }} {{ .firstName }} {{ end }}

输出:

Victor Marius Jean

首层键的移除

Hugo 在排序 Map 时会移除首层键,只保留值并返回一个切片。源码 tpl/collections/sort.go#L102-L135 遍历 Map 时只把value存入pair,键仅作为排序依据使用;最终由 pairList.sort() 构造并返回与元素类型一致的切片。

原始 Map:

{ "felix": { "breed": "malicious", "type": "cat" }, "spot": { "breed": "boxer", "type": "dog" } }

排序后得到:

[ { "breed": "malicious", "type": "cat" }, { "breed": "boxer", "type": "dog" } ]

注意排序后是按 Map 键felixspot的字典序)排列的对象切片,首层键felixspot已被去除。若希望按 Map 的排序,可传入KEY = "value";测试用例{map[string]string{"1": "10", ...}, "value", "asc", ...}即验证了该行为(见 tpl/collections/sort_test.go#L67-L68)。

排序页面集合

sort同样可以直接对页面集合(如site.RegularPages)排序。不过官方文档特别提示:虽然可以这样做,但 Hugo 提供了更专门的排序与分组方法,如ByTitleByDateByWeight等,日常优先推荐使用这些方法。

以下示例将站点的常规页面按.Type降序排列并输出标题链接:

{{ range sort site.RegularPages "Type" "desc" }} <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> {{ end }}

这里KEY = "Type"取自Page对象的字段,ORDER = "desc"实现降序。相关的性能基准测试BenchmarkWhereAndSortPages(见 tpl/collections/collections_integration_test.go#L599-L651)也印证了该用法在真实页面集合上的可行性。

源码实现原理

sort的实现位于 tpl/collections/sort.go,核心思路是键值对(pair)排序

  1. 参数解析(sort.go#L59-L72):遍历可变参数args,第 1 个作为KEY,第 2 个判断是否为"desc"以决定SortAsc标志;若第 1 个参数无法转成字符串则强制置空。
  2. 构造排序键:对切片与 Map 分别处理,沿KEY的点链路径逐级求值,得到每个元素的排序键。
  3. 比较与排序pairList实现sort.Interface(sort.go#L151-L182),其Less方法通过compare.Namespace.LtCollate配合站点语言对应的langs.Collator进行本地化感知的字符串比较——这意味着排序结果会遵循当前站点的语言规则,而不是简单的字节序比较。
  4. 稳定排序pairList.sort()使用sort.Stable(sort.go#L184-L197),保证相等元素的相对顺序不变。这一点对多级排序至关重要:例如{{ sort (sort $values "b" "asc") "a" "asc" }}先按b再按a排序,稳定性能确保第二级排序不会打乱第一级的次序。集成测试TestSortStable(Issue 9865,见 tpl/collections/collections_integration_test.go#L62-L85)专门验证了该行为。

此外,源码对小写化的 Paramshmaps.Params,即 Hugo 内部统一转为小写键的参数 Map)做了特殊处理(sort.go#L92-L96):当求值途中遇到hmaps.Params类型时,会改用GetNested按剩余路径查找,这也解释了文档中"排序 Map 时KEY必须小写"的约束来源——Hugo 的参数键在内部已统一小写。对应测试用例如".Params.COLOR"".Params.CoLoR"均能正确命中(见 tpl/collections/sort_test.go#L104-L117)。

常见错误场景

综合源码与测试用例(tpl/collections/sort_test.go#L223-L238),以下场景会触发错误,模板中应提前规避:

  • 传入nil序列 →sequence must be providedcan't iterate over a nil value
  • 传入非集合类型(如单个结构体)→can't sort <type>
  • KEY指向不存在的嵌套字段(如"foo.NotAvailable")→ 求值返回错误。

总结

collections.Sort是一个"通用、稳定、本地化感知"的排序函数:切片按value或内部字段排序,Map 排序时移除首层键并按指定(小写)字段排序,页面集合也可直接传入并按Page字段排序。理解其参数规则(KEYORDER)与底层稳定的sort.Stable实现,能让你在 Hugo 模板中写出既符合预期、又支持多级稳定排序的可靠代码。当目标只是页面集合时,别忘了 Hugo 还提供专门的页面排序方法,可参考页面排序与分组文档选择最合适的工具。

【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 17:53:52

Unity微信小游戏InputField键盘调起与回填避让实践

微信小游戏这一套环境&#xff0c;做过的朋友都清楚&#xff0c;它跟标准的WebGL发布完全是两码事。Unity里跑得好好的InputField&#xff0c;打包成小游戏丢进微信&#xff0c;点上去一点反应没有&#xff0c;键盘就是不弹——这个问题几乎每个第一次把Unity项目搬到微信小游戏…

作者头像 李华
网站建设 2026/9/18 17:52:50

Oracle 19c安装全攻略:从下载、配置到排错一站搞定

Oracle数据库的下载安装&#xff0c;网上教程一大把&#xff0c;但大多数都是“截图命令”的流水账&#xff0c;跟着走一遍容易&#xff0c;遇到问题还是懵。我最早接触Oracle的时候&#xff0c;光一个监听服务起不来就折腾了两天&#xff0c;后来才慢慢摸清楚里面的门道。所以…

作者头像 李华
网站建设 2026/9/18 17:52:15

STM32CubeProgrammer:嵌入式AI编程的最后一公里烧录指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 17:49:59

MySQL 修改密码全攻略:8.0/5.7、忘记密码与认证插件

MySQL 密码这个东西&#xff0c;平时放在那里谁也不会多看一眼&#xff0c;直到某天你打开 Navicat 或者敲下mysql -u root -p&#xff0c;回车三次都提示ERROR 1045 (28000): Access denied for user rootlocalhost&#xff0c;那一刻脑子里是空的。尤其是刚装完 MySQL 的朋友…

作者头像 李华