Skip to content

Instantly share code, notes, and snippets.

@rstropek
Created December 1, 2020 10:07
Show Gist options
  • Save rstropek/f33175e35feaa4d44a240947a5b01226 to your computer and use it in GitHub Desktop.
Save rstropek/f33175e35feaa4d44a240947a5b01226 to your computer and use it in GitHub Desktop.
Generic iterator in Go
package main
import (
"fmt"
"strings"
)
// Generic iterator function type
type iteratorFunc[T any] func() *T;
// Generic function for iteration
func next[T any](iterator iteratorFunc[T]) *T { return iterator() }
// Generic function executing a given function for each item in iterator
func forEach[T any](iterator iteratorFunc[T], body func(T)) {
for ptr := next(iterator); ptr != nil; ptr = next(iterator) {
body(*ptr)
}
}
// Generic predicate
type predicate[T any] func(item T) bool;
// Generic function filtering based on a given predicate
func filter[T any](iterator iteratorFunc[T], predicate func(T) bool) iteratorFunc[T] {
return func() *T {
var item *T
for item = next(iterator); item != nil && !predicate(*item); item = next(iterator) { }
return item
}
}
// Generic function that generates an iterator from a given slice
func iteratorFromSlice[T any](items []T) iteratorFunc[T] {
return func() *T {
if len(items) < 1 {
return nil
}
firstItem := &items[0]
items = items[1:]
return firstItem
}
}
type user struct {
name string
age int
}
func main() {
users := []user{
user{name: "Foo", age: 42},
user{name: "Bar", age: 43},
user{name: "FooBar", age: 44},
}
forEach(
filter(
iteratorFromSlice(users),
func(u user) bool { return strings.HasPrefix(u.name, "Foo"); }),
func(u user) { fmt.Printf("User is %s\n", u.name) })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment