Innovating with Go: Range Iterators Demystified

BYMark Howell 1 years ago6 MINS READ
Innovating with Go: Range Iterators Demystified

Today in Edworking News we want to talk about Introduction We're using Go to write Dolt, the world's first version-controlled SQL
database. Like most large Go codebases, we have a lot of collection types that we iterate over. New
in Go 1.23, you can now use the range keyword to iterate over custom collection types. How does that work? Is it a good idea? Let's dive in.

Copy link What are Range Iterators?

Range iterators are function types used with the built-in range keyword, starting in Go 1.23. This new feature significantly expands the power of the range keyword, which could previously only iterate over slices or maps. With range iterators, it is now possible to iterate over custom collection types. From the release notes, the new range capabilities allow for three types of loops: no arguments, one argument, or two arguments.

Example Usage

Here's a simple example to illustrate:
```go
func iter1(yield func(int) bool) bool {
for i := 0; i < 3; i++ {
if !yield(i) {
return false
}
}
return true
}
// Usage
for i := range iter1 {
fmt.Println(i)
}
// Output: 0 1 2
In this example, `iter1` is a range iterator function that runs three times.

Copy link Types of Range Iterators

Types of range iterators come in three forms based on the number of arguments they accept:

  1. Zero arguments – similar to:
    ```go
    func iter0(yield func() bool)
    ```go
    for range iter0 {
    fmt.Println("hello")
    }
    // Output: hello hello hello
  2. One argument – shown in the previous example (iter1).
  3. Two arguments – useful for scenarios needing both the index and the element:
    ```go
    func iter2(yield func(int, int) bool) bool

Copy link What Does `yield` Do?

The `yield` function within a range iterator invokes the body of the loop. When you write a range loop using an iterator, the Go compiler implicitly converts your code into function calls. For example:
```go
for i := range iter1 {
fmt.Println(i)
}
// Is implicitly converted to:
for {
var i int
var ok bool
i, ok = iter1(yield)
if !ok {
break
}
fmt.Println(i)
}
The yield function also indicates whether the loop should continue. If the result of `yield` isn't checked, the program will panic if there is a break or return statement inside the loop.

Edworking
All your work in one place
All-in-one platform for your team and your work. Register now for Free.
Get Started Now

Copy link Use Cases

Custom Collection Iteration

Range iterators shine when you need to iterate over custom collection types that aren’t maps or slices. For example, if you want to iterate over a collection of elements to filter only prime numbers:
```go
func (c *Collection) IterPrimes(yield func(int) bool) bool {
for _, v := range c.items {
if isPrime(v) {
if !yield(v) {
return false
}
}
}
return true
}
You call it like so:
```go
for prime := range myCollection.IterPrimes {
fmt.Println(prime)
}

Error Handling During Iteration

Another powerful use case is managing errors during I/O operations in iteration. For instance:
```go
func (c *Collection) IterWithErrors(yield func(int, error) bool) bool {
for _, v := range c.items {
elem, err := generateElement(v)
if !yield(elem, err) {
return false
}
}
return true
}

Sentinel Error Handling

Handling sentinel errors, such as `io.EOF`, can be streamlined using range iterators. By wrapping traditional iterators to handle end-of-loop control flows more cleanly:
```go
func (c *Collection) IterHandleSentinels(yield func(int) bool) bool {
for {
item, err := c.iterator.Next()
if err == io.EOF {
return true
}
if err != nil {
return false
}
if !yield(item) {
return false
}
}
}

Copy link Extended Use Cases: Pull and Pull2

The Go authors also provided Pull and Pull2 functions to convert range iterator functions back into traditional iterators with `Next()` methods, which can be helpful if you're working with libraries that use these new features but prefer the old iteration method.

Edworking
All your work in one place
All-in-one platform for your team and your work. Register now for Free.
Get Started Now

Copy link Readability and Conventional Considerations

One question that arises with this new flexibility is whether it's confusing for the user if the range loop's return values differ from the standard Go conventions. The community will likely develop best practices over time, but it is worth noting that for many cases, especially with slices, only the value is often of interest, not the index.

Copy link Conclusion

To delve deeper and see more examples, visit our GitHub page.

Copy link Remember these 3 key ideas for your startup:

  • Optimized Iterations: Using range iterators can enhance your codebase by providing seamless iterations over custom collections.
  • Simplified Error Management: Error handling during iterations becomes cleaner and more intuitive.
  • Enhanced Flexibility: Tailor your iteration needs more precisely to your application's requirements.
    Edworking is the best and smartest decision for SMEs and startups to be more productive. Edworking is a FREE superapp of productivity that includes all you need for work powered by AI in the same superapp, connecting Task Management, Docs, Chat, Videocall, and File Management. Save money today by not paying for Slack, Trello, Dropbox, Zoom, and Notion.
    For more details, see the original source.
Mark Howell

About the Author: Mark Howell

LinkedIn

Mark Howell is a talented content writer for Edworking's blog, consistently producing high-quality articles on a daily basis. As a Sales Representative, he brings a unique perspective to his writing, providing valuable insights and actionable advice for readers in the education industry. With a keen eye for detail and a passion for sharing knowledge, Mark is an indispensable member of the Edworking team. His expertise in task management ensures that he is always on top of his assignments and meets strict deadlines. Furthermore, Mark's skills in project management enable him to collaborate effectively with colleagues, contributing to the team's overall success and growth. As a reliable and diligent professional, Mark Howell continues to elevate Edworking's blog and brand with his well-researched and engaging content.

Startups

Try Edworking Background

A new way to work from anywhere, for everyone for Free!

Get Started Now