image
建议点击 查看原文 查看最新内容。
原文链接: https://typonotes.com/posts/2025/05/22/go1.23-iterators/
在 Go1.23 新引入了一个标准包 迭代器 Iterator[1] 。 可以返回一个 可迭代对象 - 函数, 该对象 接受一个 回调函数 - yield 。
标准包 iter 中包含以下两个类型 Seq, Seq2。 二者都返回了一个 生成器函数 yield function
type (
Seq[V any] func(yield func(V) bool)
Seq2[K, V any] func(yield func(K, V) bool)
)
Seq2 的命名方式看起来很奇怪, 感觉不太符合 golang 的命名习惯。 这里推测 2 表示接受的回调有两个参数。 func(yield func(K, V) bool)
截至 go1.24 , 目前已经有 4个 标准包支持返回迭代器了。
slices, maps: https://tip.golang.org/doc/go1.23#iteratorsstrings: https://tip.golang.org/doc/go1.24#stringspkgstringsbytes: https://tip.golang.org/doc/go1.24#bytespkgbytes这个没什么好说的, 直接看文档就行了。
迭代器的两种使用方式 回调函数 与 for 循环。
return false 提前终止遍历。Seq 返回的对象是 值, 类似于 for _, v := range []int{1,2,3} 中的 vSeq2 返回的对象是 键、值。 普通的 for 循环类似。// Seq
l := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
it1 := slices.Values(l)
for v := range it1 { // Seq 返回的是 v
println(v)
}
call1 := func(v int) bool {
if v > 5 {
returnfalse// false 提前退出
}
fmt.Println(v)
returntrue
}
it1(call1) // 1,2,3,4,5
// Seq2
m := map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}
it2 := maps.All(m)
for k, v := range it2 { // Seq2 返回的是 k, v
println(k, v)
}
call2 := func(k, v string) bool {
if k == "key2" {
returnfalse
}
println(k, v)
returntrue
}
it2(call2)
在 Go1.23 的 Release Notes[2] 中提到的 无参数迭代对象, 并没有在标准包中找到。
func(func() bool) // 无参数 <---
func(func(K) bool) // Seq: 1 参数
func(func(K, V) bool) // Seq2: 2 参数
目前我这边没想到有什么使用场景, 从语法上来看, 配合 柯里化函数 、 通道 等手段, 还是有操作性的。
// currylock 返回了一个自身计数的迭代器
func currylock() func() bool {
n := 3
i := 1
returnfunc() bool {
println(i, "<", n)
i++
if i > n {
returnfalse
}
returntrue
}
}
func seq0() {
it0 := currylock()
for it0() { // 调用的时候就像死循环。
// 其实感觉有没什么特别的。
// 就是 `for bool {}` 的模式。
}
// 1 < 3
// 2 < 3
// 3 < 3
}
参考资料
[1]
迭代器 Iterator: https://tip.golang.org/doc/go1.23#iterators
[2]
Go1.23 的 Release Notes: https://tip.golang.org/doc/go1.23#language