:判断切片、数组与字符串中是否包含指定值)
Hugo 模板函数 collections.Inin判断切片、数组与字符串中是否包含指定值【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugocollections.In是 Hugo 模板引擎提供的集合操作函数用于判断某个值是否存在于给定的切片slice、数组array或字符串中并返回布尔结果。在模板中以别名in调用常用于条件渲染、菜单或标签过滤、内容分类判断等场景。阅读本文后你将掌握in的两种匹配模式成员匹配与子串匹配、其底层实现原理以及在实际模板中的典型用法与边界行为。函数签名与基本信息根据 函数文档 的 front matter 定义函数名collections.In别名in返回类型bool签名collections.In SLICE|STRING VALUE即第一个参数是待检索的容器切片/数组或字符串第二个参数是目标值函数返回目标值是否存在于容器中。函数在模板命名空间中的注册位于 tpl/collections/init.go其中将in注册为该方法映射的别名并附带一个子串匹配的内置示例{{ if in this string contains a substring substring }}Substring found!{{ end }}基础用法判断值是否存在于切片中官方文档给出的第一个示例是切片成员匹配{{ $s : slice a b c }} {{ in $s b }} → truein会对切片逐个元素进行比较。若目标值等于其中任意一个元素返回true否则返回false。这一模式在模板中的典型应用是白名单判断例如仅对特定分类渲染内容{{ $allowed : slice news blog docs }} {{ if in $allowed .Section }} p该内容属于允许展示的板块/p {{ end }}需要注意切片匹配是严格按元素比较的目标值必须与某个元素完全相等才会命中不存在部分匹配或模糊匹配。基础用法判断子串是否存在于字符串中官方文档给出的第二个示例是字符串子串匹配{{ $s : abc }} {{ in $s b }} → true当第一个参数是字符串时in退化为子串包含判断只要第二个参数是第一个字符串的一部分即返回true。这在页面路径、URL、front matter 字段等字符串内容的条件判断中非常实用{{ if in .RelPermalink /tags/ }} 当前页面是标签页 {{ end }}底层实现原理collections.In的完整实现位于 tpl/collections/collections.go其执行逻辑分为三个阶段1. 空值短路if l nil || v nil { return false, nil }两个参数中任意一个为nil直接返回false不会报错。2. 数组/切片成员遍历lv : reflect.ValueOf(l) vv : reflect.ValueOf(v) vvk : normalize(vv) switch lv.Kind() { case reflect.Array, reflect.Slice: for i : range lv.Len() { lvv, isNil : hreflect.Indirect(lv.Index(i)) if isNil { continue } lvvk : normalize(lvv) if lvvk vvk { return true, nil } } }通过reflect判断第一个参数的底层类型是否为Array或Slice是则逐元素遍历元素为nil指针时跳过continue不参与比较每个元素与目标值都经过normalize处理后再比较这一步骤负责将类型统一归一化因此[]int{123}中的123与整数目标123能够正确匹配测试用例见 tpl/collections/where_test.go。从源码结构看normalize的目的就是消除不同数值类型间的差异让整型、浮点型等可以互相比较。3. 字符串子串回退ss, err : cast.ToStringE(l) if err ! nil { return false, nil } su, err : cast.ToStringE(v) if err ! nil { return false, nil } return strings.Contains(ss, su), nil若第一个参数不是数组/切片例如是字符串则将其与第二个参数都强制转换为字符串然后调用 Go 标准库的strings.Contains判断子串关系。这里值得注意的一个推断转换失败或字符串类型不匹配时函数返回false,nil而非报错——这也意味着当第一个参数既不是集合也不是可转字符串的值时结果恒为false。边界行为与注意事项结合源码与测试可以总结出以下边界行为场景结果依据目标值存在于切片中truecollections.go目标值不存在于切片中false同上空切片中查找任意值false测试用例{reflect.ValueOf(123), reflect.ValueOf([]int{}), in, expect{false, false}}见 where_test.go目标值为子串true子串匹配测试用例{reflect.ValueOf(foo), reflect.ValueOf(bar-foo-baz), in, expect{true, false}}见 where_test.go任意参数为nilfalsecollections.go目标值是time.Time且存在于时间切片中true测试用例见 where_test.go需要特别强调两点子串匹配是大小写敏感的in abc B返回false如需忽略大小写应结合lower/upper函数预处理后再判断。字符串子串匹配与切片成员匹配是两种截然不同的语义前者做部分包含后者做完全相等。当目标值恰好是空字符串时strings.Contains(s, )恒为true这是 Go 标准库的行为使用时需留意。与 where 操作符in的区别Hugo 的where函数也支持in/not in操作符见 tpl/collections/where.go 与 where_test.go其语义是某字段的值是否包含在给定集合中用于对页面集合做筛选。而collections.In是独立的条件判断函数直接返回布尔值。二者适用场景不同{{/* where 操作符筛选出 params.tags 字段包含 hugo 的页面 */}} {{ $pages : where .Site.RegularPages Params.tags in (slice hugo) }} {{/* collections.In 函数对单个值做包含判断 */}} {{ if in .Params.tags hugo }} 该页面打上了 hugo 标签 {{ end }}实战组合示例结合range与ifin可以写出可读性很高的条件逻辑。例如在分类页面中高亮当前激活的分类{{ $current : .Title }} ul {{ range site.Menus.main }} li class{{ if in $current .Name }}active{{ end }} a href{{ .URL }}{{ .Name }}/a /li {{ end }} /ul再如基于多个关键词的简单内容标记{{ $keywords : slice tutorial guide reference }} {{ if in $keywords .Params.category }} span classbadge精选内容/span {{ end }}总结collections.In别名in是 Hugo 模板中高频使用的小而精的函数对切片/数组执行严格的成员匹配对字符串执行子串包含匹配。理解其数组走遍历比较、字符串走strings.Contains的双路径实现以及空值短路、类型归一化、大小写敏感等边界行为能帮助你在模板开发中写出更准确、更健壮的条件判断逻辑。【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考