Gofp
A super simple Lodash like utility library with essential functions that empowers the development in Go
Install / Use
/learn @rbrahul/GofpREADME

A simple Utility library for Go
Go does not provide many essential built in functions when it comes to the data structure such as slice and map. This library provides a list of most frequently needed utility functions which are inspired by lodash(a Javascript Utility library).
Main features of gofp
-
Implementing Functional programming is way easier using
Pipe(), Compose(), Reduce(), Map(), Filter(), Extend(), Find() and many others. -
This library offers many utility function for dealing with collections or slice related operation.
-
Access any property by path or index from the map, slice and even struct by simply using the most useful function
Get. -
Utility functions are implmented based on
interface{}. The main focus is not to use thereflectpackage whenever possible.
Installation
Please run the following command in terminal to install
go get github.com/rbrahul/gofp
How to use?
This the example which describes how you can implement pipe operations using gofp
package main
import (
"fmt"
"strings"
"github.com/rbrahul/gofp"
)
func main() {
user := map[string]interface{}{
"name": "John Doe",
"age": 30,
"contacts": map[string]interface{}{
"email": "johndoe@gmail.com",
"office": "Google Inc.",
"fax": map[string]interface{}{
"uk": "+44-208-1234567",
},
},
}
getContacts := func(data interface{}) interface{} {
return data.(map[string]interface{})["contacts"]
}
getEmail := func(data interface{}) interface{} {
return data.(map[string]interface{})["email"]
}
getUpperCaseEmail := func(data interface{}) interface{} {
return strings.ToUpper(data.(string))
}
email := gofp.Pipe(
getContacts,
getEmail,
getUpperCaseEmail,
)(user)
fmt.Println("Email is: ", email) // Output: Email is: JOHNDOE@GMAIL.COM
}
Documentation:
Most commonly used utility functions for Collection or slice
Map()
Returns a new slice executing the iterator function on each element. Map has 2 parameters, 1st one is slice and 2nd one is the iterator function. The iterator function must have 2 parameters, index and current value of that iteration.
...
mappedItems := Map([]interface{}{1, 2, 3, 4, 5},
func(i int, item interface{}) interface{} {
return item.(int) * item.(int)
})
fmt.Println(mappedItems) //Output: 1, 4, 9, 16, 25
...
Filter()
Returns a new slice containing the filtered elements. The new slice contains those elements who satisfy the condition of the iterator function. Filter has 2 parameters, 1st one is the slice and 2nd one is the iterator function. The iterator function must have 2 parameters, index and current value of that iteration.
...
filteredItems := Filter([]interface{}{12, 16, 18, 20, 23, 40, 25},
func(i int, age interface{}) bool {
return age.(int) >= 20
})
fmt.Println(filteredItems) //Output: 20, 23, 40, 25
...
Find()
Returns the first matched element of the slice who satisfy the condition of iterator function. If there is no such element that satisfy the condition of the function then nil is returned. Find has 2 parameters, 1st one is the slice and 2nd one is the iterator function. The iterator function must have 2 parameters, index and current value of that iteration.
...
user := Find([]interface{}{
map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
map[string]interface{}{"name": "Roni", "sex": "male", "age": 30},
}, func(i int, person interface{}) bool {
return person.(map[string]interface{})["age"].(int) >= 18
})
fmt.Println(user) //Output: {"name": "Raymond", "sex": "male", "age": 20}
...
Reduce()
Executes a iterator function on each element of the slice, resulting in single output accumulated value. Reducer has 3 parameters, 1st one is the slice and 2nd one is the iterator function and 3rd one is the initial value. The iterator function must have 3 parameters which are index, current value of that iteration and accumulated value or result of previous iterations.
...
reducedItems := Reduce([]interface{}{10, 20, 30, 40},
func(index int, current interface{}, accumulator interface{}, source []interface{}) interface{} {
return accumulator.(int) + current.(int)
}, 0)
fmt.Println(reducedItems) //Output: 100
...
Every()
Returns true if each element matches the condition of the given iterator function. If there is any element that doesn't satisfy the condition of the function then it returns false. Every has 2 parameters, 1st one is the slice and 2nd one is the iterator function. And the iterator function must have 2 parameters, index and current value of that iteration.
...
isEveryOneIsAdult := Every([]interface{}{18, 20, 23, 40, 25},
func(i int, age interface{}) bool {
return age.(int) >= 18
})
fmt.Println(isEveryOneIsAdult) //Output: true
...
Any()
Returns true if any of the element matches the condition of the given iterator function. If there is no such element that satisfy the condition of the function then it returns false. Any has 2 parameters, 1st one is the slice and 2nd one is the iterator function. And the iterator function must have 2 parameters, index and current value of that iteration.
...
hasAnyAdult := Any([]interface{}{18, 20, 23, 40, 25},
func(i int, age interface{}) bool {
return age.(int) >= 18
})
fmt.Println(hasAnyAdult) //Output: true
...
GroupBy()
Returns a new map composed of keys generated from the results of running each element of slice thru iterator function. The order of grouped values is determined by the order they occur in slice. GroupBy has 2 parameters, 1st one is the slice and 2nd one is the iterator function. The output of the iterator function will be used as the key of the newly created group or map. And the iterator function must have 2 parameters, index and current value of that iteration.
...
groupedData := GroupBy([]interface{}{
map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
map[string]interface{}{"name": "Roni", "sex": "male", "age": 30},
}, func(person interface{}) string {
return strconv.Itoa(person.(map[string]interface{})["age"].(int))
})
fmt.Println(groupedData)
/*
Output:
{
"17": [{"name": "Ron", "sex": "male", "age": 17}],
"20": [
{"name": "Raymond", "sex": "male", "age": 20},
{"name": "Sofia", "sex": "female", "age": 20}
],
"30": [{"name": "Roni", "sex": "male", "age": 30}]
}
*/
...
Chunk()
Returns a new slice(chunks) of slices. Every slice has fixed number of elements which was given as a limit in the 2nd parameter. Chunk accepts 2 parameters, 1st one is the slice and 2nd one is the limit which will define the maxium number of elements in each slice.
...
chunkedItems := Chunk([]interface{}{1, 2, 3, 4, 5}, 2)
fmt.Println(chunkedItems) //Output: {{1,2},{3,4},{5}}
...
Reverse()
Returns a new slice with all the elements in reveresed order. Reverse accepsts 1 parameter which a slice.
...
reveresed := Reverse([]interface{}{10, 20, 30, 40, 50})
fmt.Println(reveresed) //Output: {50,40,30,20,10}
...
Range()
Returns a new slice of range where the value starts from 1st parameter to the 2nd parameter. Reverse accepsts 2 parameters, 1st one is the starting value 2nd one is the maximum value in the range.
...
rangeItems := Range(5, 10)
fmt.Println(rangeItems) //Output: {5,6,7,8,9,10}
...
Uniq()
Returns a new slice where each elements are unique removing all the duplicate elements. Uniq accepsts 1 parameter which is a slice.
...
// [1,2,3,10,4,5,100]
uniqueItems := Uniq([]interface{}{1, 2, 2, 3, 10, 4, 5, 10, 100})
fmt.Println(uniqueItems) //Output: {1,2,3,10,4,5,100}
...
Head()
Returns the first matched element of the slice. Head accepsts 1 parameter which a slice.
...
firstItem := Head([]interface{}{
map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
map[string]interface{}{"name": "Roni", "sex": "male", "age": 30},
})
fmt.Println(firstItem) //Output: {"name": "Ron", "sex": "male", "age": 17}
...
Tail()
Returns the last matched element of the slice. Head accepsts 1 parameter which a slice.
...
lastItem := Tail([]interface{}{
map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
