What is most idiomatic way to create an iterator in Go?

undefined iterator golang
google go iterator
golang import iterator
string iterator golang
golang iterate function
iterate struct golang
no more items in iterator
golang next()

One option is to use channels. Channels are like iterators in a way and you can iterate over them using range keyword. But when you find out you can't break out of this loop without leaking goroutine the usage becomes limited.

What is the idiomatic way to create iterator pattern in go?

Edit:

The fundamental problem with channels is they are a push model. Iterator is is a pull model. You don't have to tell iterator to stop. I'm looking for a way to iterate over collections in a nice expressive way. I would also like to chain iterators (map, filter, fold alternatives).

Channels are useful, but closures are often more suitable.

package main

import "fmt"

func main() {
    gen := newEven()
    fmt.Println(gen())
    fmt.Println(gen())
    fmt.Println(gen())
    gen = nil // release for garbage collection
}

func newEven() func() int {
    n := 0
    // closure captures variable n
    return func() int {
        n += 2
        return n
    }
}

Playground: http://play.golang.org/p/W7pG_HUOzw

Don't like closures either? Use a named type with a method:

package main

import "fmt"

func main() {
    gen := even(0)
    fmt.Println(gen.next())
    fmt.Println(gen.next())
    fmt.Println(gen.next())
}

type even int

func (e *even) next() int {
    *e += 2
    return int(*e)
}

Playground: http://play.golang.org/p/o0lerLcAh3

There are tradeoffs among the three techniques so you can't nominate one as idiomatic. Use whatever best meets your needs.

Chaining is easy because functions are first class objects. Here's an extension of the closure example. I added a type intGen for integer generator which makes it clear where generator functions are used as arguments and return values. mapInt is defined in a general way to map any integer function to an integer generator. Other functions such as filter and fold could be defined similarly.

package main

import "fmt"

func main() {
    gen := mapInt(newEven(), square)
    fmt.Println(gen())
    fmt.Println(gen())
    fmt.Println(gen())
    gen = nil // release for garbage collection
}

type intGen func() int

func newEven() intGen {
    n := 0
    return func() int {
        n += 2
        return n
    }
}

func mapInt(g intGen, f func(int) int) intGen {
    return func() int {
        return f(g())
    }
}

func square(i int) int {
    return i * i
}

Playground: http://play.golang.org/p/L1OFm6JuX0

What is most idiomatic way to create an iterator in Go?, One option is to use channels. Channels are like iterators in a way and you can iterate over them using range keyword. But when you find out you can't break out​  What is the idiomatic way of creating a go iterator? Showing 1-12 of 12 messages. > // and are now considered the idiomatic go iterator pattern.

What is the idiomatic way of creating a go iterator?, What is the go way of generating an iterator for separate distinct arrays/slices I'​d like a more "yieldy" way of iterating when it's more natural to What is the idiomatic way to create iterator pattern in go? Edit: The fundamental problem with channels is they are a push model. Iterator is is a pull model. You don't have to tell iterator to stop. I'm looking for a way to iterate over collections in a nice expressive way. I would also like to chain iterators (map, filter, fold alternatives).

TL;DR: Iterators are not idiomatic in Go. Leave them to other languages.

In depth then, the Wikipedia entry "Iterator pattern" begins, "In object-oriented programming, the iterator pattern is a design pattern..." Two red flags there: First, object oriented programming concepts often don't translate well into Go, and second, many Go programmers don't think much of design patterns. That first paragraph also includes "The iterator pattern decouples algorithms from containers", but only after stating "an iterator [accesses] the container's elements. Well which is it? If an algorithm is accessing the container's elements it can hardly claim to be decoupled. The answer in many languages involves some kind of generics that allows the language to generalize over similar data structures. The answer in Go is interfaces. Interfaces enforce a stricter decoupling of algorithms and objects by denying access to structure and requiring all interaction be based on behavior. Behavior means capabilites expressed through methods on the data.

For a minimal iterator type the needed capability is a Next method. A Go interface can represent an iterator object by simply specifying this single method signature. If you want a container type to be iterable, it must satisfy the iterator interface by implementing all of the methods of the interface. (We only have one here, and in fact it is common for interfaces to have only a single method.)

A minimal working example:

package main

import "fmt"

// IntIterator is an iterator object.
// yes, it's just an interface.
type intIterator interface {
    Next() (value int, ok bool)
}

// IterableSlice is a container data structure
// that supports iteration.
// That is, it satisfies intIterator.
type iterableSlice struct {
    x int
    s []int
}

// iterableSlice.Next implements intIterator.Next,
// satisfying the interface.
func (s *iterableSlice) Next() (value int, ok bool) {
    s.x++
    if s.x >= len(s.s) {
        return 0, false
    }
    return s.s[s.x], true
}

// newSlice is a constructor that constructs an iterable
// container object from the native Go slice type.
func newSlice(s []int) *iterableSlice {
    return &iterableSlice{-1, s}
}

func main() {
    // Ds is just intIterator type.
    // It has no access to any data structure.
    var ds intIterator

    // Construct.  Assign the concrete result from newSlice
    // to the interface ds.  ds has a non-nil value now,
    // but still has no access to the structure of the
    // concrete type.
    ds = newSlice([]int{3, 1, 4})

    // iterate
    for {
        // Use behavior only.  Next returns values
        // but without insight as to how the values
        // might have been represented or might have
        // been computed.
        v, ok := ds.Next()
        if !ok {
            break
        }
        fmt.Println(v)
    }
}

Playground: http://play.golang.org/p/AFZzA7PRDR

This is the basic idea of interfaces, but it's absurd overkill for iterating over a slice. In many cases where you would reach for an iterator in other languages, you write Go code using built in language primitives that iterate directly over basic types. Your code stays clear and concise. Where that gets complicated, consider what features you really need. Do you need to emit results from random places in some function? Channels provide a yield-like capability that allows that. Do you need infinite lists or lazy evaluation? Closures work great. Do you have different data types and you need them to transparently support the same operations? Interfaces deliver. With channels, functions, and interfaces all first class objects, these techniques are all easily composable. So what then is the most idiomatic way? It is to experiment with different techniques, get comfortable with them, and use whatever meets your needs in the simplest way possible. Iterators, in the object oriented sense anyway, are almost never simplest.

Iterators in Go, When writing Go code, it often feels like a (slightly verbose) scripting Or, a more realistic question – when I'm writing code, which version should I look at are a) how does the iterator implementation work and b) compared  Go programmers, those both new and experienced, are susceptible to being led astray from the most idiomatic path. These "anti-patterns" are sometimes easier to spot than idiomatic Go. We'll cover some common anti-patterns from Edward's talk, which will help guide you towards idiomatic go.

You can break out without leaking by giving your goroutines a second channel for control messages. In the simplest case it's just a chan bool. When you want the goroutine to stop, you send on this channel. Inside the goroutine, you put the iterator's channel send and the listen on the control channel inside a select.

Here's an example.

You can take this further by allowing different control messages, such as "skip".

Your question is pretty abstract, so to say more, a concrete example would be helpful.

Iterator patterns in Go, I'm less concerned about complexity in the iterator implementation, but handling this correctly It's trying to force a Python or OCaml idiom on to Go. Channels and goroutines are also a very Go-like way to process data. Before then, I'd recommend just doing an iterator and returning Box<Iterator<Item=XXX>>. If you need more performance and aren't on nightly already, it can sometimes also be feasible to create a new structure which stores state manually and implements Iterator, and to return that.

Looking to the container/list package it looks like there is no way to do it. C-like way should be used if you iterate over object.

Something like this.

type Foo struct {
...
}

func (f *Foo) Next() int {
...
}

foo := Foo(10)

for f := foo.Next(); f >= 0; f = foo.Next() {
...
}

Custom range iterators in Go : golang, For example, iterating over lines of input or traversing a more complex data How I write an opensource cloud gaming service with WebRTC and Golang. Idiomatic Go programs have semicolons only in places such as for loop clauses, to separate the initializer, condition, and continuation elements. They are also necessary to separate multiple statements on a line, should you write code that way.

3 ways to iterate in Go, 3 different way to implement an iterator in Go: callbacks, channels, struct with Before discussing different ways of designing iteration API, let's see how we Channel-based iterator is easy to implent and use by the caller but most expensive. Idiomatic way of creating duration or future date. Ask Question. 1. What would be the idiomatic way of getting a duration between two dates or basically getting a future date based on the current. Right now I'm using the below code to achieve that.

Yielding Functions for Iteration in Go · Libelli, It is very common for me to design code that expects functions to return an in Go, I often want to apply the same pattern, but iteration in Go is very This pattern speaks to me, it is exactly how I think about constructing iterable functions​. This simple programming construct (which is Go idiomatic) does  Of course when the container offers random access iterators, one can leverage the iterator difference, but then you can't use the range-for: std::vector<std::string> items; for (auto it = items.begin(); it != items.end(); ++it) *it += std::to_string(it - items.begin());

Effective Go, This document gives tips for writing clear, idiomatic Go code. It augments the language specification, the Tour of Go, and How to Write Go Code, all of which you Formatting issues are the most contentious but the least consequential. The bug is that in a Go for loop, the loop variable is reused for each iteration, so the req  The simplest example is finding the max element of collection, but is not a good one: the operation here is idempotent. More realistic example is table dumping by portions: at first request we create a file with header for columns, then populate it. What is the common approach (or most idiomatic way) to implementation of this pattern?

Comments
  • Channels carry events. This doesn't mean they have to have a push model, it just depends on how you use them. If you use them in a linear way, you get a push model. If you use them in a client/server way, you can have a pull model instead.
  • Very nice. But you can't use range keyword with closure. Can you provide an example of for loops? How does iteration stop? You probably need a second return value to indicate that.
  • Range works with built in types, not user defined things like functions. You're right that you could use a second return value to stop iteration. That would be clear and idomatic. You might also just stop iterating when you've found what you are looking for or when you have processed the desired amount of data.
  • Note that if you actually know how much data you will process, it probably makes sense just to store it all in a slice. That should be fine unless you are processing a really huge amount of data that doesn't fit comfortably in memory. If you want, you make sure to release all references to the data when you're done with it and then it can be garbage collected. And of course with a slice, you can use range.
  • So I played fast and loose with the meaning of "iterator" here to try to show some useful techniques. Apologies for chasing wishes and not answering the question as asked. In my second attempt at an answer I tried to follow a more rigorous definition.
  • Thanks for the example. I didn't notice function literals in Go are closures until now. It's wonderful!
  • "performance wise it's a no-Go" I like the pun, but I'm not sure I agree with the conclusion. Looking at your numbers, I see that all of them are within about a 3x difference of each other, and my first thought is that you should arbitrarily choose whichever you think is most expressive, unless you have actually profiled the code and determined that this iteration is a meaningful bottleneck in your application. In many applications, the work inside the loop will dominate, and this level of iteration difference will be negligible.
  • Well I agree that c++ iterators are not that simple. But compare to Python generators or IEnumerable<T> in C#. Your last paragraph is great, maybe I need to experiment with different techniques in place of traditional iterators.
  • This is an amazing answer with quite a lot of depth to it. @Sonia, have you considered writing a "Way of Go" type of book or blog series?
  • Iterators are very idiomatic in Go, and there are a number of examples in the standard library including bufio.Scanner and tar.Reader off the top of my head.
  • That is pretty contrived for a simple iteration. How about performance?
  • I use this model a lot because it's otherwise pretty hard to have a paginated, but arbitrarily long data stream you want to consume. -- BTW, just close that channel when you're done with it. close is a persistent send.