Go has no Python-style generators with yield. You express lazy sequences with functions returning channels, callbacks, iterators (Go 1.23+ range over functions), or plain slice indices.
func ints(n int) <-chan int {
ch := make(chan int)
go func() {
defer close(ch)
for i := 0; i < n; i++ {
ch <- i
}
}()
return ch
}
Remember: channels are for communication; not every loop needs a goroutine.
The standard library adds iterator patterns (iter package). You can for v := range seq when seq yields values per the language spec. Check your Go version and go doc iter.
func readLines(next func() (string, bool)) {
for {
line, ok := next()
if !ok {
break
}
_ = line
}
}
range on slices, maps, strings, and channels is the idiomatic iteration mechanism.
Channel-based pipelines add synchronization overhead. For CPU-bound inner loops, prefer plain for with indices or slices/maps helpers (Go 1.21+).