资讯动态

lo 库 it.FilterValues 详解:Go 1.23 迭代器风格的 map 值过滤函数

发布时间:2026/9/13 7:38:21 来源:尧图企业网站定制
lo 库 it.FilterValues 详解Go 1.23 迭代器风格的 map 值过滤函数【免费下载链接】lo A Lodash-style Go library based on Go 1.18 Generics (map, filter, contains, find...)项目地址: https://gitcode.com/GitHub_Trending/lo/lo本文聚焦 lo 库 it 包中的 FilterValues 函数讲解其函数签名、谓词用法与全部示例场景并结合 it/map.go 的源码实现、it/map_test.go 的测试用例说明它作为iter.Seq惰性序列的工作原理以及与 core 包中同步切片版本 lo.FilterValues 的差异帮助读者在 Go 1.23 的迭代器场景下正确选择和使用这一工具函数。一、函数定位与核心语义it.FilterValues是 lo 库面向 Go 1.23 引入的iter标准库设计的序列化工具之一。其官方文档描述为Filters map values based on a predicate function that takes both key and value. Returns a slice of values that satisfy the predicate.根据一个同时接收键和值的谓词函数过滤 map 的值返回满足谓词的值切片。函数签名如下定义在 it/map.gofunc FilterValuesK comparable, V any bool) iter.Seq[V]关键参数说明参数约束/类型说明Kcomparablemap 键类型要求可比较Vanymap 值类型任意类型inmap[K]V待过滤的输入 mappredicatefunc(key K, value V) bool谓词函数同时接收键与值返回true时该值被保留返回值iter.Seq[V]惰性序列可被range遍历或slices.Collect收集为切片从源码注释看FilterValues被明确定位为 “a mix of Filter and Values”——即Filter按条件筛选与Values提取 map 值两个能力的组合遍历时对每个键值对执行谓词判断只有判断为真时才把值 yield 出去。二、完整示例场景以下示例完整继承自官方文档 docs/data/it-filtervalues.md覆盖数值过滤、字符串长度过滤、键值联合判断、空 map 与浮点数过滤五类典型场景。由于it包基于 Go 1.23 的iter.Seq实现实际使用时通常先用slices.Collect把序列收集为切片再断言结果package main import ( fmt iter slices strings github.com/samber/lo/it ) func collectV any []V { return slices.Collect(seq) } func main() { // 场景 1数值过滤取出值大于 2 的元素 m : map[string]int{ apple: 3, banana: 5, cherry: 2, date: 0, } result : collect(it.FilterValues(m, func(key string, value int) bool { return value 2 })) // 值为 3 和 5对应 apple 和 banana元素顺序不保证 // 场景 2字符串长度过滤取出长度为 3 的值 numberMap : map[int]string{1: one, 2: two, 3: three, 4: four} result collect(it.FilterValues(numberMap, func(key int, value string) bool { return len(value) 3 })) // one、two、three // 场景 3键与值联合判断键以 a 开头且年龄 20 personMap : map[string]int{alice: 25, bob: 30, charlie: 17} result collect(it.FilterValues(personMap, func(key string, age int) bool { return strings.HasPrefix(key, a) age 20 })) // 仅 alice 的值 25 // 场景 4空 map谓词恒为 true 也不产生任何元素 emptyMap : map[string]int{} result collect(it.FilterValues(emptyMap, func(key string, value int) bool { return true })) // 空切片 // 场景 5浮点数过滤只保留正值 dataMap : map[string]float64{a: 1.5, b: -2.0, c: 0.0, d: 3.14} result collect(it.FilterValues(dataMap, func(key string, value float64) bool { return value 0 })) // 1.5 和 3.14 fmt.Println(result) }需要特别注意的是文档示例注释中把结果写作[]int{3, 5}这类形式但由于 Go map 本身的遍历顺序是随机的FilterValues输出序列中元素的相对顺序并不保证与 map 键的某种排列一致。因此对结果做精确切片比较时建议先排序或使用ElementsMatch之类的无序断言。三、源码级实现剖析it.FilterValues的完整实现见 it/map.go// FilterValues transforms a map into a sequence based on predicate returns true for specific elements. // It is a mix of Filter and Values. func FilterValuesK comparable, V any bool) iter.Seq[V] { return func(yield func(V) bool) { for k, v : range in { if predicate(k, v) !yield(v) { return } } } }从源码结构看其实现包含三个值得关注的细节返回的是闭包而非切片。函数体并不立即遍历 map而是返回一个捕获了in与predicate的函数值。只有当调用方真正range这个序列时map 遍历才会发生这是一种惰性求值lazy evaluation模式。对yield返回值的检查实现了提前终止。yield(v)返回false时闭包立刻return这意味着消费方在迭代中途break或return时谓词不会在剩余键值对上被白白执行。这一点在测试基础设施 it/lo_test.go 的assertSeqSupportBreak辅助函数中有系统性验证// assertSeqSupportBreak checks whether it is possible to break iteration over a [iter.Seq]. func assertSeqSupportBreakT any iter.Seq[T] { t.Helper() assert.NotPanics(t, func() { for range seq { break } for range seq { return } }) return seq }该实现受编译条件约束。it/map.go 文件首行带有//go:build go1.23构建标签因此it包的所有函数包括FilterValues只在 Go 1.23 及以上工具链下参与编译。项目整体 go.mod 声明的最低版本是 Go 1.18即 core 包兼容 Go 1.18而it包是面向 Go 1.23 迭代器标准库的增量扩展。四、与 core 包 lo.FilterValues 的对照同一个仓库中core 包提供了同步切片版本的 lo.FilterValues其签名与文档中的 core 版一致// FilterValues transforms a map into a slice based on predicate returns true for specific elements. // It is a mix of lo.Filter() and lo.Values(). func FilterValuesK comparable, V any bool) []V { result : make([]V, 0, len(in)) for k, v : range in { if predicate(k, v) { result append(result, v) } } return result }两个版本的对应关系可以归纳为维度lo.FilterValuescoremap.goit.FilterValuesit/map.go返回值[]V立即物化为切片iter.Seq[V]惰性序列执行时机调用即遍历整个 map被 range/Collect 时才遍历提前终止不支持谓词必然跑完所有条目支持yield 返回 false 即停止运行环境Go 1.18泛型即可Go 1.23依赖标准库iter包典型搭配直接使用slices.Collect收集或与其他iter.Seq组合如果下游逻辑需要错误处理能力core 包还有带错误返回的 FilterValuesErr谓词签名变为func(key K, value V) (bool, error)谓词一旦返回非空 error迭代立即停止并返回该错误。而it包的 map.go 目前提供的是无错误变体的FilterValues从源码结构看若需要“错误 迭代器”的组合可以先用 core 的FilterValuesErr收集为切片再按需转换。五、相关函数与组合使用在 it/map.go 中FilterValues与一族 map 序列化工具紧邻定义可自然组合FilterKeys与FilterValues对称返回满足谓词的键序列即 “Filter Keys” 的组合Values不带谓词返回全部值的序列。FilterValues可以理解为Values加上了按 key/value 判断的闸门Keys、Entries分别返回键序列与键值对序列是 map 到序列转换的基础工具FilterMapToSeq谓词升级为转换函数func(key K, value V) (R, bool)在过滤的同时做类型变换功能上是FilterValues的泛化。一个典型的组合用法先用FilterValues筛出值序列再交给it包的其他序列函数做二次处理例如排序后取前 N 项整个过程无需中间切片分配。六、测试用例验证it.FilterValues的行为在 it/map_test.go 中有专门的单元测试TestFilterValues包含两个子场景func TestFilterValues(t *testing.T) { t.Parallel() t.Run(string values filtered by matching predicate, func(t *testing.T) { t.Parallel() is : assert.New(t) result1 : FilterValues(map[int]string{1: foo, 2: bar, 3: baz}, func(k int, v string) bool { return v foo }) assertSeqSupportBreak(t, result1) is.Equal([]string{foo}, slices.Collect(result1)) }) t.Run(int values with predicate always false, func(t *testing.T) { t.Parallel() is : assert.New(t) result2 : FilterValues(map[string]int{foo: 1, bar: 2, baz: 3}, func(k string, v int) bool { return false }) is.Empty(slices.Collect(result2)) }) }第一个子用例验证正常过滤路径只保留值为foo的条目并在收集结果前先执行assertSeqSupportBreak确认中途break/return不会导致 panic第二个子用例验证谓词恒为false时序列为空。此外it/map_example_test.go 提供了可直接运行的示例测试func ExampleFilterValues() { kv : map[int]string{1: foo, 2: bar, 3: baz} result : slices.Collect(FilterValues(kv, func(k int, v string) bool { return v foo })) fmt.Printf(%v, result) // Output: [foo] }运行go test ./it/即可复现上述验证需 Go 1.23 工具链以满足it/map.go的构建标签。七、使用要点小结版本前提it.FilterValues依赖 Go 1.23 的标准库iter包文件头部的构建标签见 it/map.go低版本环境应改用 core 包 map.go 中的同步切片版本。惰性语义返回的iter.Seq[V]可被多次range每次都会重新遍历底层 map 并重新执行谓词若需要固化结果用slices.Collect一次性收集。顺序不确定结果顺序继承自 map 的随机遍历顺序做断言或对外输出时不要假设固定排列。谓词同时拿到 key 和 value这是FilterValues相对“先Values再filter”两步写法的核心优势——单步内即可完成键值联合判断且只遍历 map 一次。组合方向与 FilterKeys、Entries、FilterMapToSeq 等函数共同构成 it 包的 map 序列化工具体系需要错误处理时参考 core 包 FilterValuesErr 的设计。【免费下载链接】lo A Lodash-style Go library based on Go 1.18 Generics (map, filter, contains, find...)项目地址: https://gitcode.com/GitHub_Trending/lo/lo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价