Patterns: behavior · 3 MIN READ
Iterator: yield values without exposing storage
Use iter.Seq or a small Next API and honor early termination.
Use iter.Seq or a small Next API and honor early termination. Iterator gives callers sequential access without revealing collection internals. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.
Behavioral pattern · A MAP OF THE IDEA
- Producer generates a value
- Consumer receives it through yield
- False return stops production
Useful when
- Traversal should hide collection representation
- Values can be produced lazily
Watch out
- Errors and cleanup need explicit contracts
- A slice range may already be sufficient
Implementation & operation cost: Low
Fit depends on the task
Editorial suitability, not benchmarks or a universal ranking. Styles describe different axes and can be combined.
The design decision
Iterator gives callers sequential access without revealing collection internals. Modern Go supports range over iterator functions through iter.Seq. A producer must stop when yield returns false; continuing work after the caller breaks wastes resources and can violate the iterator contract.
A complete Go example
Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.
package main
import (
"fmt"
"iter"
)
func CountTo(n int) iter.Seq[int] {
return func(yield func(int) bool) {
for i := 1; i <= n; i++ {
if !yield(i) {
return
}
}
}
}
func main() {
for n := range CountTo(5) {
fmt.Println(n)
if n == 2 {
break
}
}
}
// Output:
// 1
// 2
CountTo hides how values are generated and stops immediately after the caller breaks at two. iter.Seq is available from Go 1.23. The iterator uses no goroutine or channel because synchronous production is enough.
Tradeoffs and the simpler alternative
For fallible streams, define how errors are delivered, such as iter.Seq2[Value, error] or an Err method. Resource-owning iterators need cleanup on early termination. Ranging a slice is simpler when the caller already owns a small in-memory collection.
TAKE THIS WITH YOU
Must stop producing when yield returns false. For fallible streams, define how errors are delivered, such as iter.Seq2[Value, error] or an Err method. Resource-owning iterators need cleanup on early termination. Ranging a slice is simpler when the caller already owns a small in-memory collection.
Check your understanding
Which statement best describes Iterator: yield values without exposing storage?
Go to the source
Progress stays in this browser. No account needed.