Goava is a set of libraries based on draft version of Go 2 generics.
Read the blog post about this project
It's not ready for production or even development use.
Bugs found while working on this project:
Read more about the draft design of Go Generics: The Next Step for Generics
Of([]int{1, 2, 3, 4})
or
Of([]string{"q", "w", "e"})
Let's get rid of some numbers:
stream.
Of([]int{1, 2, 3, 4, 5}).
Filter(func(x int) bool {
return x%2 == 0
}).
Slice()
Let's get rid of some numbers
stream.Map(
stream.Of([]int{1, 2}),
func(x int) string { return fmt.Sprint(x) },
).Slice()
Stream(Type).AnyMatch(func(Type) bool)
returns true if any of elements in stream match given predicateStream(Type).NoneMatch(func(Type) bool)
returns true if none of elements in stream match given predicateStream(Type).AllMatch(func(Type) bool)
returns true if all of elements in stream match given predicate
Define a stream of movies with name and score that users gave:
items := stream.Of(
[]MovieVote{
{Name: "A", Score: 1},
{Name: "A", Score: 2},
{Name: "B", Score: 9},
{Name: "B", Score: 10},
{Name: "B", Score: 8},
{Name: "C", Score: 7},
{Name: "C", Score: 8},
{Name: "C", Score: 7},
},
)
Now let's collect create a hashmap where key is a name of movie and value is sum of scores:
result := stream.Collect(
items,
collector.ToMap(MovieVote, string, int)(
func(movie MovieVote) (string, int) {
return movie.Name, movie.Score
},
func(total, score int) int {
return total + score
},
),
)
The first argument to ToMap
is a mapper, it receives original item and returns a tuple of key and value. The second
argument to ToMap
is a accumulator, it current value and new value given by mapper or during combining parallel stream
chunks. Yes, parallel.
A stream can be switched to parallel mode, so mapping and accumulation will be done in concurrent mode.
items = items.Parallel()
A stream can be switched back to sequential mode by calling Sequential()
function.
The main goal was to bring Rust's powerful Result to Go. Unfortunately, it can't be ported completely due to lack of pattern matching in Go.
The only possible way was to use channels and select {}, but it would be too complicated and it would be just an imitation.
Methods implemented so far:
IsOk returns true if the result is Ok.
IsErr returns true if the result is Err.
And returns res if the result is Ok, otherwise returns the Err value of self.
OrElse Calls fn if the result is Err, otherwise returns the Ok value of self.
Returns res if the result is Err, otherwise returns the Ok value of self.
OK returns the contained Ok value. Panics if the result is an Err
Err returns the contained Err value. Panics if the result is Ok
OkOr returns the contained Ok value or a provided default.
OkOrElse returns the contained Ok value or calls provided fn.
Expect returns the contained Ok value. Panics if the value is an Err, with a panic message including the passed message, and the content of the Err.
Expect returns the contained Err value. Panics if the value is an Ok, with a panic message including the passed message, and the content of the Ok.
func Success() Result(int) {
return Ok(42)
}
func Fail() Result(int) {
return Err(int)(errors.New("failure"))
}
func main() {
fmt.Println(Fail().OrElse(Success))
result := Success().And(Fail())
if result.IsOk() {
fmt.Println("it's ok", result.Ok())
} else {
fmt.Println("it's not ok, but here is default value:", result.OkOr(1))
}
}
MIT