I’m going to change gears from the previous discussion about goroutines, to different ways of iterating. This can closely relate to goroutines, so we’ll bounce back and forth a bit, I suspect. Meanwhile, if you have any questions specifically about goroutines that I didn’t cover, send me an email. I’ll be happy to fill in those gaps!
First off, before really diving into iterator patterns, let’s talk about why we might want iterators. This will help frame the larger discussion.
string := "Hello, world!"
str := "Hello, world!"
for _, char := range str {
fmt.Println(char)
}
This code loops over each character of the string Hello, world!
, and prints the ASCII value of each character, one per line:
72
101
108
108
...
And, of course, we use loops similar to this (though typically more interesting) all the time. That is, we frequently need to iterate over a number of items. And the simplest way to do this is often with a simple for loop, as illustrated.
And for such a small string, this approach is fine. But what if our input were much longer? Perhaps megabytes or gigabytes in size? And maybe we’re doing something more involved that simply printing each character in turn? Maybe the thing we’re doing involves a non-trivial amount of calculation, or consumes a lot of memory, or involves spawning multiple goroutines…
Depending on these, and other factors, we often want something more sophisticated than a simple for
loop.
What other options do we have? Of course we’ll be diving into the details, but here’s a preview:
- index-based for loops
- channels
- range-over-func for loops
- custom iterators