Lazy like a koala, smart like a chimpanzee
Koazee is a StreamLike, Immutable, Lazy Loading and smart Golang Library to deal with slices.
Visit the Koazee wiki to find out what Koazee can do.
- Immutable: Koazee won't modify your inputs.
- StreamLike: We can combine operations up our convenience.
- Lazy loading: Operations are not performed until they're required
- Generic: Koazee provides a generic interface able to deal with slice of any type without creating custom functions.
- Focusing on performance: First rule for implementing a new operation is providing the best possible performance.
Add Koazee to your project
Go modules
module github.com/me/project
require (
github.com/wesovilabs/koazee vX.Y.Z
)
Glide
glide get github.com/wesovilabs/koazee
Go dep
go get github.com/wesovilabs/koazee
Let's first obtain a stream from an existing array.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
)
var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}
func main() {
fmt.Printf("slice: %v\n", numbers)
stream := koazee.StreamOf(numbers)
fmt.Printf("stream: %v\n", stream.Out().Val())
}
/**
go run main.go
slice: [1 5 4 3 2 7 1 8 2 3]
stream: [1 5 4 3 2 7 1 8 2 3]
*/
Current release v0.0.3 (Gibbon) brings us 20 generic operations that are showed below
These operations return an element from the stream
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
)
var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}
func main() {
stream := koazee.StreamOf(numbers)
fmt.Printf("stream.At(4): %d\n", stream.At(4).Int())
fmt.Printf("stream.First: %d\n", stream.First().Int())
fmt.Printf("stream.Last: %d\n", stream.Last().Int())
}
/**
go run main.go
stream.At(4): 2
stream.First: 1
stream.Last: 3
*/
These operations add or delete elements from the stream.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
)
var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}
func main() {
fmt.Printf("input: %v\n", numbers)
stream := koazee.StreamOf(numbers)
fmt.Print("stream.Add(10): ")
fmt.Println(stream.Add(10).Do().Out().Val())
fmt.Print("stream.Drop(5): ")
fmt.Println(stream.Drop(5).Do().Out().Val())
fmt.Print("stream.DropWhile(val<4): ")
fmt.Println(stream.DropWhile(func(element int)bool{return element<4}).Do().Out().Val())
fmt.Print("stream.DeleteAt(4): ")
fmt.Println(stream.DeleteAt(4).Do().Out().Val())
fmt.Print("stream.Set(0,5): ")
fmt.Println(stream.Set(0, 5).Do().Out().Val())
fmt.Print("stream.Pop(): ")
val, newStream := stream.Pop()
fmt.Printf("%d ... ", val.Int())
fmt.Println(newStream.Out().Val())
}
/**
go run main.go
input: [1 5 4 3 2 7 1 8 2 3]
stream.Add(10): [1 5 4 3 2 7 1 8 2 3 10]
stream.Drop(5): [1 4 3 2 7 1 8 2 3]
stream.DeleteAt(4): [1 5 4 3 7 1 8 2 3]
stream.Set(0,5): [5 5 4 3 2 7 1 8 2 3]
stream.Pop(): 1 ... [5 4 3 2 7 1 8 2 3]
*/
These operations return info from the elements in the stream
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
)
var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}
func main() {
fmt.Printf("input: %v\n", numbers)
stream := koazee.StreamOf(numbers)
count, _ := stream.Count()
fmt.Printf("stream.Count(): %d\n", count)
index, _ := stream.IndexOf(2)
fmt.Printf("stream.IndexOf(2): %d\n", index)
index, _ = stream.LastIndexOf(2)
fmt.Printf("stream.LastIndexOf(2): %d\n", index)
contains, _ := stream.Contains(7)
fmt.Printf("stream.Contains(7): %v\n", contains)
}
/**
go run main.go
input: [1 5 4 3 2 7 1 8 2 3]
stream.Count(): 10
stream.IndexOf(2): 4
stream.LastIndexOf(2): 8
stream.Contains(7): true
*/
These operations organize the elements in the stream.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
"strings"
)
var animals = []string{"lynx", "dog", "cat", "monkey", "fox", "tiger", "lion"}
func main() {
fmt.Print("input: ")
fmt.Println(animals)
stream := koazee.StreamOf(animals)
fmt.Print("stream.Reverse(): ")
fmt.Println(stream.Reverse().Out().Val())
fmt.Print("stream.Sort(strings.Compare): ")
fmt.Println(stream.Sort(strings.Compare).Out().Val())
}
/**
go run main.go
input: [lynx dog cat monkey fox tiger lion]
stream.Reverse(): [lion tiger fox monkey cat dog lynx]
stream.Sort(strings.Compare): [cat dog fox lion lynx monkey tiger]
*/
These operations return a filtered stream.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
)
var animals = []string{"lynx", "dog", "cat", "monkey", "dog", "fox", "tiger", "lion"}
func main() {
fmt.Print("input: ")
fmt.Println(animals)
stream := koazee.StreamOf(animals)
fmt.Print("stream.Take(1,4): ")
fmt.Println(stream.Take(1, 4).Out().Val())
fmt.Print("stream.Filter(len==4): ")
fmt.Println(stream.
Filter(
func(val string) bool {
return len(val) == 4
}).
Out().Val(),
)
fmt.Print("stream.RemoveDuplicates(): ")
fmt.Println(stream.RemoveDuplicates().Out().Val())
}
/**
go run main.go
input: [lynx dog cat monkey dog fox tiger lion]
stream.Take(1,4): [dog cat monkey dog]
stream.Filter(len==4): [lynx lion]
stream.RemoveDuplicates(): [lynx dog cat monkey fox tiger lion]
*/
This operation performs a modification over all the elements in the stream.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
"strings"
)
var animals = []string{"lynx", "dog", "cat", "monkey", "dog", "fox", "tiger", "lion"}
func main() {
fmt.Printf("input: %v\n", animals)
stream := koazee.StreamOf(animals)
fmt.Print("stream.Map(strings.Title): ")
fmt.Println(stream.Map(strings.Title).Do().Out().Val())
}
/**
go run main.go
input: [lynx dog cat monkey dog fox tiger lion]
stream.Map(strings.Title): [Lynx Dog Cat Monkey Dog Fox Tiger Lion]
*/
This operation give us a single output after iterating over the elements in the stream.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
)
var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}
func main() {
fmt.Printf("input: %v\n", numbers)
stream := koazee.StreamOf(numbers)
fmt.Print("stream.Reduce(sum): ")
fmt.Println(stream.Reduce(func(acc, val int) int {
return acc + val
}).Int())
}
/**
go run main.go
input: [1 5 4 3 2 7 1 8 2 3]
stream.Reduce(sum): 36
*/
This operation iterates over the element in the stream.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
)
type message struct {
user string
message string
}
var messages = []*message{
{user: "John", message: "Hello Jane"},
{user: "Jane", message: "Hey John, how are you?"},
{user: "John", message: "I'm fine! and you?"},
{user: "Jane", message: "Me too"},
}
func main() {
stream := koazee.StreamOf(messages)
stream.ForEach(func(m *message) {
fmt.Printf("%s: \"%s\"\n", m.user, m.message)
}).Do()
}
/**
go run main.go
John: "Hello Jane"
Jane: "Hey John, how are you?"
John: "I'm fine! and you?"
Jane: "Me too"
*/
The main goal of Koazee is providing a set of operations that can be combined and being evaluated lazily.
package main
import (
"fmt"
"github.com/wesovilabs/koazee"
"strings"
)
type Person struct {
Name string
Male bool
Age int
}
var people = []*Person{
{"John Smith", true, 32},
{"Peter Pan", true, 17},
{"Jane Doe", false, 20},
{"Anna Wallace", false, 35},
{"Tim O'Brian", true, 13},
{"Celia Hills", false, 15},
}
func main() {
stream := koazee.
StreamOf(people).
Filter(func(person *Person) bool {
return !person.Male
}).
Sort(func(person, otherPerson *Person) int {
return strings.Compare(person.Name, otherPerson.Name)
}).
ForEach(func(person *Person) {
fmt.Printf("%s is %d years old\n", person.Name, person.Age)
})
fmt.Println("Operations are not evaluated until we perform stream.Do()\n")
stream.Do()
}
/**
go run main.go
Operations are not evaluated until we perform stream.Do()
Anna Wallace is 35 years old
Celia Hills is 15 years old
Jane Doe is 20 years old
*/
A rich and growing set of examples can be found on koazee-samples
You can check the Benchmark for the Koazee operations here
A benchmark comparison with other frameworks can be found in Koazee vs Go-Funk vs Go-Linq
This is only the beginning! By the way, If you missed any operation in Koazee v0.0.3, or you found a bug, please create a new issue on Github or vote the existing ones!