-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
While https://pkg.go.dev/iter does a good job at explaining the basics of iterators, it leaves out a few important bits of information which may be really useful when writing APIs with iterators. The two most important of them being:
- Whether an exported func or method should itself be an iterator, or return an iterator.
The consensus seems to be to export funcs which return iterators, e.g. func (*Foo) Bars() iter.Seq[Bar] used like for bar := range foo.Bars(), rather than func (*Foo) Bars(yield func(Bar) bool) used like for bar := range foo.Bars. This is a bit more consistent with cases where one needs to supply parameters to obtain an iterator, as then the iterator must be a return parameter.
See #66626 (comment), for example, where @adonovan originally proposed adding methods to go/types which were directly iterators.
- How errors should be returned to the caller.
If an iteration can fail with an error, it's not obvious whether to return one top-level error, like func Foo() (iter.Seq[Bar], error), or to provide an error at each iteration step, like func Foo() iter.Seq2[Bar, error]. Arguments can be made either way, but I think fundamentally one can implement any reasonable semantics with either signature.
The original proposal at #61897 seemed to clearly favor iter.Seq2[Bar, error] via its func Lines(file string) iter.Seq2[string, error] example, yet none of the value-error examples or text have survived into the final godoc we have today.
As of today I think there is no clear consensus for errors; as recently as last October it was still being discussed as part of a new API proposal.
There may be other API conventions that the iter godoc should mention as well, but these two seem like the most important to me. I would suggest that we document these guidelines sooner than later, so that iterator APIs across the Go ecosystem can be reasonably consistent and predictable.