|
|
|
|
|
by throwaway894345
1655 days ago
|
|
The problem with using channels is that these require multiple goroutines and locking for a problem that's inherently singlethreaded. Instead, you can define an iterator as a function that returns a function: func intSliceIter(ints []int) func() (int, bool) {
i := 0
return func() (int, bool) {
if i < len(ints) {
ret := ints[i]
i++
return ret, true
}
return 0, false
}
}
iter := intSliceIter([]int{0, 1, 2, 3, 4})
for x, ok := iter(); ok; x, ok = iter() {
fmt.Println(x)
}
Of course, there's not much benefit to a SliceIter; this is a contrived example, but you can apply this pattern in more complicated cases as well. Similarly, you can define an iterator as an interface (which is similar to bufio.Scanner and a few others in the standard library—a closure is an object is a closure): type IntIter interface {
Next() (int, bool)
}
type IntSliceIter struct {
Cursor int
Ints []int
}
func (isi *IntSliceIter) Next() (int, bool) {
if isi.Cursor < len(isi.Ints) {
ret := isi.Ints[isi.Cursor]
isi.Cursor++
return ret, true
}
return 0, false
}
|
|