Go - Iterator Patterns
Updated at 2013-11-18 06:54
Iteration pattern allows a programmer to traverse a container without knowing anything about the implementation. Closely resembles a basic for-loop.
package main
import "fmt"
func main() {
letters := []string{"a", "b", "c", "d"}
for index, item := range letters {
fmt.Printf("[%d]: %s\n", index, item)
}
}
Callback iterator pattern is the fastest.
package main
import "fmt"
// Iterator.
func IntCallbackIterator(integers []int, callback func(int)) {
for _, value := range integers {
callback(value)
}
}
// Usage
func main() {
var sum int = 0
var numbers = []int{1, 2, 3, 4}
IntCallbackIterator(numbers, func(value int) {
sum += value
})
fmt.Println(sum)
}
Closure iterator pattern is pretty close to callback iterator in performance.
package main
import "fmt"
// Container returns this.
type IntIterator interface {
Next() (int, bool)
}
// Iterator.
func IntClosureIterator(integers []int) (func() (int, bool), bool) {
var index = 0
var length = len(integers)
return func() (int, bool) {
var prevIndex = index
index++
return integers[prevIndex], (index < length)
}, (index < length)
}
// Usage
func main() {
var sum = 0
var numbers = []int{1, 2, 3, 4}
var currentValue = 0
for it, hasNext := IntClosureIterator(numbers); hasNext; {
currentValue, hasNext = it()
sum += currentValue
}
fmt.Println(sum)
}
Channel iterator pattern is the most natural to use in Go.
package main
import "fmt"
func IntChannelIterator(integers []int) <-chan int {
ch := make(chan int, len(integers))
go func() {
for _, value := range integers {
ch <- value
}
close(ch)
}()
return ch
}
func main() {
var sum = 0
var numbers = []int{1, 2, 3, 4}
for value := range IntChannelIterator(numbers) {
sum += value
}
fmt.Println(sum)
}