迭代器概述
其他编程语言多年来一直拥有迭代器这一结构。Go 在 1.23 版本中引入了迭代器。迭代器是一种用于遍历数据结构(如切片、映射等)元素的“抽象”。虽然使用索引也能达到相同的效果,但迭代器通过抽象循环逻辑,提供了不仅仅是遍历所有元素的功能。它们可以过滤切片并创建批次(参见 myslices.Chunks 文章)。通过迭代器,你可以在循环的代价下完成更多的事情。
在 Go 1.23 之前的切片遍历方法
在 Go 1.23 之前,你有多种选择来遍历切片的元素:
Do While / While 循环 For 循环 Range 循环
从 Go 1.23 开始
正如我们在介绍中提到的,Go 1.23 引入了迭代器来遍历数据结构的元素。那么,Go 中的迭代器是什么呢?
根据文档,迭代器是一个函数,它将序列的连续元素传递给一个回调函数(生成器),通常称为 yield。当序列结束或生成器函数返回 false 时,迭代器函数会停止,表示迭代应该提前终止。
编写一个切片迭代器
让我们编写一个迭代器来遍历切片的元素。乍一看可能有些复杂,深入理解后也是如此。😆
我们将其分解为几个部分来理解它的功能:
sliceValueIterator
:迭代器函数是一个可以在 range 语句后调用的函数;迭代器函数以切片( slice []int
)作为参数;迭代器函数返回一个以生成器(yield)作为参数的函数; 生成器是一个函数,接受切片的值并返回一个布尔值:当这个布尔值为 false 时,迭代器将停止循环的执行; 传递给生成器函数的参数是你想在循环中读取的值。在这个例子中是 value
。
如果我们还想获取索引,我们可以这样写:
现在我们在循环中需要两个值:
项目的索引 项目的值
根据第 5 点,生成器必须接受两个值。可以看到,generatorWithIndex
是一个接受两个整数作为参数并返回布尔值的函数。完美!
Seq 和 Seq2 类型
在标准库中,你会发现这两种类型定义在 iter
包中:
Seq
Seq2
它们与 func(generator)
和 func(generatorWithIndex)
类型相同,但使用了泛型,因此你可以生成任何类型的值。它们定义如下:
type (
Seq[V any] func(yield func(V) bool)
Seq2[K, V any] func(yield func(K, V) bool)
)
如果我们用这些类型重写示例,我们会得到:
结论
我认为对于像这样的简单任务,使用迭代器并没有明显的优势。这里使用的示例旨在介绍和理解 Go 1.23 中这个新概念的基本原理。希望这篇文章能帮助你更好地理解标准库中如 slices
包中那些新函数背后的机制。
点击关注并扫码添加进交流群
免费领取「Go 语言」学习资料