Go Range Iterators Demystified
The Go 1.23 release introduces range iterators for custom collection types, offering flexibility for iteration beyond maps and slices. These iterators support various loop forms and enable powerful iteration scenarios.
Read original articleIn the latest Go 1.23 release, range iterators have been introduced, allowing iteration over custom collection types using the range keyword. Three types of range iterator functions are available, each corresponding to different forms of the range loop. These functions can take 0, 1, or 2 arguments, enabling various iteration scenarios. The yield function within a range iterator is crucial, as it invokes the loop body and controls loop continuation based on its return value.
Range iterators offer flexibility for iterating over collections beyond maps and slices, enabling scenarios like filtering values based on specific criteria, handling errors during iteration, and converting traditional iterators to be compatible with the range keyword. While this new feature may challenge existing conventions, such as returning only values without keys or indexes, it provides a concise and powerful way to work with custom collection types. As developers explore and adopt range iterators, their diverse applications and potential benefits are expected to become clearer over time.
Related
Interface Upgrades in Go (2014)
The article delves into Go's interface upgrades, showcasing their role in encapsulation and decoupling. It emphasizes optimizing performance through wider interface casting, with examples from io and net/http libraries. It warns about complexities and advises cautious usage.
Continuations by Example
Continuations are powerful in control-flow constructs, enabling exceptions, search, threads, generators, and coroutines. They capture remaining computation steps, aiding in non-deterministic choices and efficient iteration over data structures.
Writing generic collection types in Go: the missing documentation
The blog post delves into challenges of implementing generic collection types in Go, focusing on creating a sortable Set. The author faces compilation errors, explores solutions, and discovers syntax for generic type constraints, enhancing understanding.
Know Go: Iterators in Go
Iterators in Go yield results one at a time, enhancing efficiency. They are detailed in function signatures, error handling, composition, and library impact. Compared to channels, iterators offer simplicity and efficiency.
Enums in Go
This article explores emulating enums in Go, a language lacking native support. It covers defining custom types with strings or integers, utilizing the iota keyword, implementing interfaces, custom marshalling, and tools like go-enum.
func (s Slice) All() func(yield func(i int) bool) {
return func(yield func(i int) bool) {
for i := range s {
if !yield(s[i]) {
return
}
}
}
}
”So, for an “easy enough” example correctly, you have to write func five times in order to, if I understand this correctly, wrote a function returning a function that takes a function as an argument?
For comparison, C# does that this way (https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...)
IEnumerable<int> ProduceEvenNumbers(int upto)
{
for (int i = 0; i <= upto; i += 2)
{
yield return i;
}
}
Yes, that introduces “magic” where the runtime figures out that ProduceEvenNumbers won’t continue, but why give such functions the flexibility not to listen to such requests (in the golang version, is forgetting the if and just yielding instead ever useful?)I give it 10 more years of such special cased improved, for Go not to be any better than the languages the community regularly complains about, while Go is "perfect".
// Only care about the iteration count
for range aContainer { ... }
// Just the values
for v := range myChannel { ... }
// Indexes and values (or keys and values for a map)
for i, v := range mySlice { ... }
My understanding is that internal iteration makes it easier to write iterators (producers) but harder to write the consuming code. That's why Go needs to re-write the body of each `for` loop as a function body, including special handling for `break`, `return` etc.
External iteration OTOH makes it harder to write producers but easier to write consumers. Python and C# therefore allow external iterators to be written via coroutines/generators.
Wouldn't Go's goroutines make the coroutine approach to external iterators straightforward? Whereas the re-writing necessary for internal iterators seems convoluted?
Compare that to yield return, .Select and .Where methods in C#, or Filter and Map in many popular languages - it's not a good look.
Or when writing manually, compare it to
static IEnumerable<T> Filter<T>(
IEnumerable<T> source, Func<T, bool> predicate)
{
foreach (var item in source)
{
if (predicate(item))
yield return item;
}
}
Could also compare to how easy it is to use for extremely common patterns in general purpose code: var numbers = Enumerable.Range(0, 10);
var even = numbers.Where(n => n % 2 is 0);
var strings = even.Select(n => n.ToString());
Related
Interface Upgrades in Go (2014)
The article delves into Go's interface upgrades, showcasing their role in encapsulation and decoupling. It emphasizes optimizing performance through wider interface casting, with examples from io and net/http libraries. It warns about complexities and advises cautious usage.
Continuations by Example
Continuations are powerful in control-flow constructs, enabling exceptions, search, threads, generators, and coroutines. They capture remaining computation steps, aiding in non-deterministic choices and efficient iteration over data structures.
Writing generic collection types in Go: the missing documentation
The blog post delves into challenges of implementing generic collection types in Go, focusing on creating a sortable Set. The author faces compilation errors, explores solutions, and discovers syntax for generic type constraints, enhancing understanding.
Know Go: Iterators in Go
Iterators in Go yield results one at a time, enhancing efficiency. They are detailed in function signatures, error handling, composition, and library impact. Compared to channels, iterators offer simplicity and efficiency.
Enums in Go
This article explores emulating enums in Go, a language lacking native support. It covers defining custom types with strings or integers, utilizing the iota keyword, implementing interfaces, custom marshalling, and tools like go-enum.