How do generics combine with Go 1.23 iterators (iter.Seq)? Write lazy Filter and Map adapters and explain the yield contract.
Question 140HardGo 1.22 to 1.25
iter.Seq[V] is a generic function type, func(yield func(V) bool), and iter.Seq2[K, V] is the two-value form. for v := range seq calls seq with a compiler-generated yield. Adapters are generic functions that wrap one sequence in another. They are lazy: no intermediate slices are built, and they can be infinite.
func Filter[V any](seq iter.Seq[V], keep func(V) bool) iter.Seq[V] {
return func(yield func(V) bool) {
for v := range seq {
if keep(v) && !yield(v) {
return // consumer stopped: MUST stop
}
}
}
}
func Map[V, U any](seq iter.Seq[V], f func(V) U) iter.Seq[U] {
return func(yield func(U) bool) {
for v := range seq {
if !yield(f(v)) {
return
}
}
}
}
func Naturals() iter.Seq[int] {
return func(yield func(int) bool) {
for i := 0; ; i++ {
if !yield(i) {
return
}
}
}
}
for s := range Map(Filter(Naturals(), func(n int) bool { return n%3 == 0 }), strconv.Itoa) {
if s == "12" {
break
}
fmt.Print(s, " ") // 0 3 6 9
}
The contract: when yield returns false (because the loop body executed break, return or goto), the iterator must stop and must never call yield again. Violating that causes a runtime panic: "range function continued iteration after function for loop body returned false". Also, defer inside the iterator runs when the iterator function returns, which makes it a good place to release resources.
More on Generics
- Q138Explain the
cmppackage:Compare,Less,Or. How do you do a multi-key sort, and how is NaN handled? - Q139Which generic helpers in
slicesandmapsshould a senior Go developer know, and what are their gotchas? - Q141What is
iter.Pull, and when do you need it? Implement a genericZip. - Q142What are generic type aliases (Go 1.24), and how do they differ from generic type definitions?
- Q143Are generic types covariant? Can a
Box[Dog]be used as aBox[Animal], or aBox[int]converted to aBox[MyInt]? - Q144What is an "instantiation cycle"? Why does this recursive generic function fail to compile?