The entire concept of Go was summarized in a single loop which is for. Currently, I'm reviewing a codebase in which somebody ranges over a function that yields into a callback that returns a boolean in order to stop early.
The language that bragged about being boring
Go language gained popularity because it deliberately avoided being too clever. Just structs, loops, and interfaces. That was the agreement. You could look at anyone's Go and get it within five minutes. The agreement was violated in August 2024 with the release of Go 1.23 which introduced iterators using range over func syntax as iter.Seq and iter.Seq2. All of a sudden, you were required to have an understanding of push iterators, pull iterators, yield callbacks, and boolean returns for early termination, which are four new concepts to implement something that could already be achieved with a for loop.
Then the standard library drank the Kool-Aid
In February 2026, the Go 1.26 version was released with a rich set of new features. The reflect package was revamped to include iterators such as Type.Fields, Type.Methods, Value.Fields, and Value.Methods. The old NumField and Field(i) loop? That's right, there's now an iterator version of that. So, whether you liked iterators or not, the stdlib is now all about them. As of August 2026, the ecosystem had become fully saturated. You can't escape this. It's in the libraries you import, the snippets you paste, the code review you reluctantly sign off on. The community was divided into two equal parts. Half of a developer forum was referring to it as "finally elegant". The other half was saying "you ruined the language."
The part nobody wants to hear: it's slower
Here's the twist. All this expressive power costs you. In September 2024, Google Developer Expert Val Deleplace benchmarked it and found that "ranging over an iterator is also somewhat slower than directly ranging over a slice or a map." Hence, you pay for an abstraction. In a study conducted by Rost Glukhov in January 2025, custom iterators were pitted against classical data structures. The finding was that the custom iterator "rarely executes faster than the classical approach," and the decision "boils down to aesthetic reasons."
We made it complicated for aesthetic reasons.
Go is speedrunning Rust envy
In 2026, Iterium was introduced. It implemented the concepts of Python's itertools and Rust, which are lazy pipelines, in Go. It included functions like Map, Filter, TakeWhile, and DropWhile. To be honest, it is fast. The benchmarks were run on Linux x86_64 with Go 1.26.2. It streamed 10,000,000 values through a Range -> map -> filter pipeline in 0.06 seconds. However, if you look at the current situation, those individuals who abandoned Rust due to its complexity are now using Go to reconstruct Rust. Dave Cheney provided an overview of the resistance long time ago, in a 2017 proposal about short function literals: "Please no, clear is better than clever." This statement has turned into a prophecy.
Complexity you can hide is still complexity
I was annoyed by this, and then I read a comment from a veteran dev that completely put my feelings into words. They described the 1.23 iterators as "a way to hide complexity, make reasoning about code more difficult and are completely unnecessary."
Disguising the complexity does not mean eliminating it. Instead, it shifts the complexity to a point where you are likely to encounter it when you least expect it. Ok, here's the deal:
ā Go's superpower was readability over cleverness, not raw feature count
ā Adding expressive power to a deliberately simple tool betrays the people who picked it for simplicity
ā "It's optional" falls apart once the standard library uses it everywhere
ā A slower, harder-to-read version of a for loop is not a win
I don't have a problem with iterators! They work well in a language designed for them. The concept of the Go language was built on the idea that "you don't need this." Now, if you ask "how do I loop" it's a bit more complicated. š
The takeaway
With Go, the promise was that the person who comes after you and reads your code should not need a manual. And then the iterators came along and converted that promise into a full freaking chapter! Or perhaps we simply rebuilt what drove everyone away in the beginning. So which camp are you in: is range-over-func the elegance Go was missing, or did we hand a simple language a footgun it never asked for?
Top comments (1)
Counter-data-point, offered gently: we run 63k lines of Go on 1.26 ā 213 files, 589 range loops, exactly zero iter.Seq. That's not a policy. Nobody ever proposed one, and nobody ever needed one.
Which makes me think "you can't escape this" is the weakest link here. reflect.Type.Fields doesn't replace NumField, it sits next to it. An addition you can decline is a very different animal from a signature that changed under you.
The line I'd keep is the other one: complexity you can hide is still complexity. That one isn't really about iterators. It applies to anything that reads as done because nobody watched it work ā I spent yesterday finding four CI guards in exactly that state, and two of them had never rejected anything in their lives.
Ask me again the day a library we depend on returns an iter.Seq and we have to consume it. That's when "it's optional" actually gets tested.