go-funk
A modern Go utility library which provides helpers (map, find, contains, filter, ...)
Top Related Projects
💥 A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find...)
🍕 Enjoy a slice! A utility library for dealing with slices and maps that focuses on type safety and performance.
A collection of generic data structures written in Go.
.NET LINQ capabilities in Go
Quick Overview
The go-funk
library is a collection of common and useful functions for the Go programming language. It provides a set of functional programming utilities that can be used to simplify and streamline various tasks in Go projects.
Pros
- Extensive Functionality: The library offers a wide range of functions covering various use cases, from working with collections and data structures to performing string manipulations and more.
- Readability and Expressiveness: The functions in
go-funk
are designed to be intuitive and easy to use, making the code more readable and maintainable. - Performance: The library is optimized for performance, with many of the functions being implemented in a way that minimizes overhead and maximizes efficiency.
- Active Development and Community: The project is actively maintained, with regular updates and contributions from the community.
Cons
- Dependency Management: Using the
go-funk
library may introduce an additional dependency in your project, which could potentially increase the complexity of dependency management. - Potential Overhead: While the library is optimized for performance, there may be cases where the overhead of using the functions outweighs the benefits, especially for simple or highly performance-critical tasks.
- Learning Curve: Developers new to functional programming or the
go-funk
library may need to invest some time in understanding the available functions and how to use them effectively. - Potential Duplication with Standard Library: Some of the functionality provided by
go-funk
may overlap with the standard Go library, which could lead to confusion or redundancy in certain cases.
Code Examples
Here are a few examples of how to use the go-funk
library:
- Filtering a Slice:
package main
import (
"fmt"
"github.com/thoas/go-funk"
)
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evenNumbers := funk.Filter(numbers, func(n int) bool {
return n%2 == 0
}).([]int)
fmt.Println(evenNumbers) // Output: [2 4 6 8 10]
}
- Mapping a Slice:
package main
import (
"fmt"
"github.com/thoas/go-funk"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
squares := funk.Map(numbers, func(n int) int {
return n * n
}).([]int)
fmt.Println(squares) // Output: [1 4 9 16 25]
}
- Reducing a Slice:
package main
import (
"fmt"
"github.com/thoas/go-funk"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
sum := funk.Reduce(numbers, func(acc, n int) int {
return acc + n
}, 0)
fmt.Println(sum) // Output: 15
}
- Flattening a Slice of Slices:
package main
import (
"fmt"
"github.com/thoas/go-funk"
)
func main() {
slices := [][]int{{1, 2}, {3, 4}, {5, 6}}
flattened := funk.Flatten(slices).([]int)
fmt.Println(flattened) // Output: [1 2 3 4 5 6]
}
Getting Started
To use the go-funk
library in your Go project, follow these steps:
- Install the library using the Go package manager:
go get github.com/thoas/go-funk
- Import the library in your Go file:
import "github.com/thoas/go-funk"
- Start using the functions provided by the
go-funk
library in your code. For example:
numbers := []int{1,
Competitor Comparisons
💥 A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find...)
Pros of lo
- Better performance due to use of generics
- More comprehensive set of functions and utilities
- Active development and maintenance
Cons of lo
- Requires Go 1.18+ for generics support
- Slightly steeper learning curve due to more advanced features
- May have more dependencies
Code Comparison
lo:
names := lo.Map([]string{"Samuel", "John", "Alice"}, func(name string, _ int) string {
return strings.ToUpper(name)
})
go-funk:
names := funk.Map([]string{"Samuel", "John", "Alice"}, func(name string) string {
return strings.ToUpper(name)
})
Both libraries provide similar functionality, but lo leverages Go's generics for improved type safety and performance. The go-funk example uses reflection, which can be slower and less type-safe.
lo offers a more extensive set of utility functions and is actively maintained, making it a strong choice for modern Go projects. However, go-funk may be preferable for projects using older Go versions or those seeking a simpler API.
Ultimately, the choice between lo and go-funk depends on your project requirements, Go version compatibility, and performance needs.
🍕 Enjoy a slice! A utility library for dealing with slices and maps that focuses on type safety and performance.
Pros of pie
- Generates type-safe code for specific types, reducing runtime errors
- Offers better performance due to compile-time code generation
- Provides a wider range of functions and operations
Cons of pie
- Requires code generation step, adding complexity to the build process
- Limited to predefined types, less flexible for custom types
- Larger codebase due to generated code for each type
Code Comparison
pie:
//go:generate pie All(string)
type StringSlice []string
func main() {
names := StringSlice{"Alice", "Bob", "Charlie"}
filtered := names.Filter(func(name string) bool {
return len(name) > 3
})
}
go-funk:
import "github.com/thoas/go-funk"
func main() {
names := []string{"Alice", "Bob", "Charlie"}
filtered := funk.Filter(names, func(name string) bool {
return len(name) > 3
})
}
pie generates type-specific code, resulting in a more verbose but type-safe implementation. go-funk uses reflection, offering a more concise but less type-safe approach. pie requires a code generation step, while go-funk can be used directly. Both libraries provide similar functionality, but pie offers better performance and compile-time safety at the cost of additional complexity and code generation.
A collection of generic data structures written in Go.
Pros of generic
- Utilizes Go 1.18+ generics for type-safe operations
- Provides a more extensive set of generic data structures and algorithms
- Offers better performance due to compile-time type checking
Cons of generic
- Requires Go 1.18 or later, limiting compatibility with older codebases
- Has a steeper learning curve due to its more complex generic implementations
- Less mature and potentially less stable compared to go-funk
Code comparison
go-funk:
names := []string{"John", "Jane", "Bob"}
upperNames := funk.Map(names, func(name string) string {
return strings.ToUpper(name)
})
generic:
names := []string{"John", "Jane", "Bob"}
upperNames := slices.Map(names, strings.ToUpper)
Summary
generic leverages Go's newer generics feature to provide type-safe operations and a wider range of data structures and algorithms. It offers better performance but requires a more recent Go version and may have a steeper learning curve. go-funk, on the other hand, is more established and works with older Go versions but lacks the type safety and performance benefits of generics. The code comparison shows that generic can lead to more concise code in some cases.
.NET LINQ capabilities in Go
Pros of go-linq
- More comprehensive set of LINQ-like operations
- Supports both generic and non-generic implementations
- Better performance in some scenarios due to lazy evaluation
Cons of go-linq
- Steeper learning curve for developers not familiar with LINQ
- Slightly more verbose syntax in some cases
- Less idiomatic Go code compared to go-funk
Code Comparison
go-linq:
From(users).Where(func(u interface{}) bool {
return u.(User).Age > 30
}).Select(func(u interface{}) interface{} {
return u.(User).Name
}).ToSlice(&result)
go-funk:
result := funk.Map(funk.Filter(users, func(u User) bool {
return u.Age > 30
}), func(u User) string {
return u.Name
})
Both libraries provide functional programming utilities for Go, but they differ in their approach and syntax. go-linq offers a more comprehensive set of operations inspired by .NET's LINQ, while go-funk provides a simpler, more Go-idiomatic approach. The choice between them depends on your specific needs, familiarity with LINQ concepts, and preference for coding style.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
go-funk
.. image:: https://secure.travis-ci.org/thoas/go-funk.svg?branch=master :alt: Build Status :target: http://travis-ci.org/thoas/go-funk
.. image:: https://godoc.org/github.com/thoas/go-funk?status.svg :alt: GoDoc :target: https://pkg.go.dev/github.com/thoas/go-funk
.. image:: https://goreportcard.com/badge/github.com/thoas/go-funk :alt: Go report :target: https://goreportcard.com/report/github.com/thoas/go-funk
go-funk
is a modern Go library based on reflect_.
Generic helpers rely on reflect_, be careful this code runs exclusively on runtime so you must have a good test suite.
These helpers have started as an experiment to learn reflect_. It may look like lodash_ in some aspects but
it will have its own roadmap. lodash_ is an awesome library with a lot of work behind it, all features included in
go-funk
come from internal use cases.
You can also find typesafe implementation in the godoc_.
Why this name?
Long story, short answer because func
is a reserved word in Go, I wanted something similar.
Initially this project was named fn
I don't need to explain why that was a bad idea for french speakers :)
Let's funk
!
.. image:: https://media.giphy.com/media/3oEjHQKtDXpeGN9rW0/giphy.gif
<3
Installation
.. code-block:: bash
go get github.com/thoas/go-funk
Usage
.. code-block:: go
import "github.com/thoas/go-funk"
These examples will be based on the following data model:
.. code-block:: go
type Foo struct {
ID int
FirstName string `tag_name:"tag 1"`
LastName string `tag_name:"tag 2"`
Age int `tag_name:"tag 3"`
}
func (f Foo) TableName() string {
return "foo"
}
With fixtures:
.. code-block:: go
f := &Foo{
ID: 1,
FirstName: "Foo",
LastName: "Bar",
Age: 30,
}
You can import go-funk
using a basic statement:
.. code-block:: go
import "github.com/thoas/go-funk"
funk.Contains .............
Returns true if an element is present in a iteratee (slice, map, string).
One frustrating thing in Go is to implement contains
methods for each type, for example:
.. code-block:: go
func ContainsInt(s []int, e int) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
this can be replaced by funk.Contains
:
.. code-block:: go
// slice of string
funk.Contains([]string{"foo", "bar"}, "bar") // true
// slice of Foo ptr
funk.Contains([]*Foo{f}, f) // true
funk.Contains([]*Foo{f}, func (foo *Foo) bool {
return foo.ID == f.ID
}) // true
funk.Contains([]*Foo{f}, nil) // false
b := &Foo{
ID: 2,
FirstName: "Florent",
LastName: "Messa",
Age: 28,
}
funk.Contains([]*Foo{f}, b) // false
// string
funk.Contains("florent", "rent") // true
funk.Contains("florent", "foo") // false
// even map
funk.Contains(map[int]string{1: "Florent"}, 1) // true
funk.Contains(map[int]string{1: "Florent"}, func(key int, name string) bool {
return key == 1 // or `name == "Florent"` for the value type
}) // true
see also, typesafe implementations: ContainsInt_, ContainsInt64_, ContainsFloat32_, ContainsFloat64_, ContainsString_
.. _ContainsFloat32: https://godoc.org/github.com/thoas/go-funk#ContainsFloat32 .. _ContainsFloat64: https://godoc.org/github.com/thoas/go-funk#ContainsFloat64 .. _ContainsInt: https://godoc.org/github.com/thoas/go-funk#ContainsInt .. _ContainsInt64: https://godoc.org/github.com/thoas/go-funk#ContainsInt64 .. _ContainsString: https://godoc.org/github.com/thoas/go-funk#ContainsString
funk.Intersect ..............
Returns the intersection between two collections.
.. code-block:: go
funk.Intersect([]int{1, 2, 3, 4}, []int{2, 4, 6}) // []int{2, 4}
funk.Intersect([]string{"foo", "bar", "hello", "bar"}, []string{"foo", "bar"}) // []string{"foo", "bar"}
see also, typesafe implementations: IntersectString
.. IntersectString: https://godoc.org/github.com/thoas/go-funk#IntersectString
funk.Difference ..............
Returns the difference between two collections.
.. code-block:: go
funk.Difference([]int{1, 2, 3, 4}, []int{2, 4, 6}) // []int{1, 3}, []int{6}
funk.Difference([]string{"foo", "bar", "hello", "bar"}, []string{"foo", "bar"}) // []string{"hello"}, []string{}
see also, typesafe implementations: DifferenceString
.. DifferenceString: https://godoc.org/github.com/thoas/go-funk#DifferenceString
funk.IndexOf ............
Gets the index at which the first occurrence of a value is found in an array or return -1 if the value cannot be found.
.. code-block:: go
// slice of string
funk.IndexOf([]string{"foo", "bar"}, "bar") // 1
funk.IndexOf([]string{"foo", "bar"}, func(value string) bool {
return value == "bar"
}) // 1
funk.IndexOf([]string{"foo", "bar"}, "gilles") // -1
see also, typesafe implementations: IndexOfInt_, IndexOfInt64_, IndexOfFloat32_, IndexOfFloat64_, IndexOfString_
.. _IndexOfFloat32: https://godoc.org/github.com/thoas/go-funk#IndexOfFloat32 .. _IndexOfFloat64: https://godoc.org/github.com/thoas/go-funk#IndexOfFloat64 .. _IndexOfInt: https://godoc.org/github.com/thoas/go-funk#IndexOfInt .. _IndexOfInt64: https://godoc.org/github.com/thoas/go-funk#IndexOfInt64 .. _IndexOfString: https://godoc.org/github.com/thoas/go-funk#IndexOfString
funk.LastIndexOf ................
Gets the index at which the last occurrence of a value is found in an array or return -1 if the value cannot be found.
.. code-block:: go
// slice of string
funk.LastIndexOf([]string{"foo", "bar", "bar"}, "bar") // 2
funk.LastIndexOf([]string{"foo", "bar", "bar"}, func(value string) bool {
return value == "bar"
}) // 2
funk.LastIndexOf([]string{"foo", "bar"}, "gilles") // -1
see also, typesafe implementations: LastIndexOfInt_, LastIndexOfInt64_, LastIndexOfFloat32_, LastIndexOfFloat64_, LastIndexOfString_
.. _LastIndexOfFloat32: https://godoc.org/github.com/thoas/go-funk#LastIndexOfFloat32 .. _LastIndexOfFloat64: https://godoc.org/github.com/thoas/go-funk#LastIndexOfFloat64 .. _LastIndexOfInt: https://godoc.org/github.com/thoas/go-funk#LastIndexOfInt .. _LastIndexOfInt64: https://godoc.org/github.com/thoas/go-funk#LastIndexOfInt64 .. _LastIndexOfString: https://godoc.org/github.com/thoas/go-funk#LastIndexOfString
funk.ToMap ..........
Transforms a slice or an array of structs to a map based on a pivot
field.
.. code-block:: go
f := &Foo{
ID: 1,
FirstName: "Gilles",
LastName: "Fabio",
Age: 70,
}
b := &Foo{
ID: 2,
FirstName: "Florent",
LastName: "Messa",
Age: 80,
}
results := []*Foo{f, b}
mapping := funk.ToMap(results, "ID") // map[int]*Foo{1: f, 2: b}
funk.ToSet ..........
Transforms an array or a slice to a set (a map with zero-size values).
.. code-block:: go
f := Foo{
ID: 1,
FirstName: "Gilles",
LastName: "Fabio",
Age: 70,
}
b := Foo{
ID: 2,
FirstName: "Florent",
LastName: "Messa",
Age: 80,
}
mapping := funk.ToSet([]Foo{f, b}) // map[Foo]stuct{}{f: struct{}{}, b: struct{}{}}
mapping := funk.ToSet([4]int{1, 1, 2, 2}) // map[int]struct{}{1: struct{}{}, 2: struct{}{}}
funk.Filter ...........
Filters a slice based on a predicate.
.. code-block:: go
r := funk.Filter([]int{1, 2, 3, 4}, func(x int) bool {
return x%2 == 0
}) // []int{2, 4}
see also, typesafe implementations: FilterInt_, FilterInt64_, FilterFloat32_, FilterFloat64_, FilterString_
.. _FilterFloat32: https://godoc.org/github.com/thoas/go-funk#FilterFloat32 .. _FilterFloat64: https://godoc.org/github.com/thoas/go-funk#FilterFloat64 .. _FilterInt: https://godoc.org/github.com/thoas/go-funk#FilterInt .. _FilterInt64: https://godoc.org/github.com/thoas/go-funk#FilterInt64 .. _FilterString: https://godoc.org/github.com/thoas/go-funk#FilterString
funk.Reduce ...........
Reduces an iteratee based on an accumulator function or operation rune for numbers.
.. code-block:: go
// Using operation runes. '+' and '*' only supported.
r := funk.Reduce([]int{1, 2, 3, 4}, '+', float64(0)) // 10
r := funk.Reduce([]int{1, 2, 3, 4}, '*', 1) // 24
// Using accumulator function
r := funk.Reduce([]int{1, 2, 3, 4}, func(acc float64, num int) float64 {
return acc + float64(num)
}, float64(0)) // 10
r := funk.Reduce([]int{1, 2, 3, 4}, func(acc string, num int) string {
return acc + fmt.Sprint(num)
}, "") // "1234"
funk.Find .........
Finds an element in a slice based on a predicate.
.. code-block:: go
r := funk.Find([]int{1, 2, 3, 4}, func(x int) bool {
return x%2 == 0
}) // 2
see also, typesafe implementations: FindInt_, FindInt64_, FindFloat32_, FindFloat64_, FindString_
.. _FindFloat32: https://godoc.org/github.com/thoas/go-funk#FindFloat32 .. _FindFloat64: https://godoc.org/github.com/thoas/go-funk#FindFloat64 .. _FindInt: https://godoc.org/github.com/thoas/go-funk#FindInt .. _FindInt64: https://godoc.org/github.com/thoas/go-funk#FindInt64 .. _FindString: https://godoc.org/github.com/thoas/go-funk#FindString
funk.Map ........
Manipulates an iteratee (map, slice) and transforms it to another type:
- map -> slice
- map -> map
- slice -> map
- slice -> slice
.. code-block:: go
r := funk.Map([]int{1, 2, 3, 4}, func(x int) int {
return x * 2
}) // []int{2, 4, 6, 8}
r := funk.Map([]int{1, 2, 3, 4}, func(x int) string {
return "Hello"
}) // []string{"Hello", "Hello", "Hello", "Hello"}
r = funk.Map([]int{1, 2, 3, 4}, func(x int) (int, int) {
return x, x
}) // map[int]int{1: 1, 2: 2, 3: 3, 4: 4}
mapping := map[int]string{
1: "Florent",
2: "Gilles",
}
r = funk.Map(mapping, func(k int, v string) int {
return k
}) // []int{1, 2}
r = funk.Map(mapping, func(k int, v string) (string, string) {
return fmt.Sprintf("%d", k), v
}) // map[string]string{"1": "Florent", "2": "Gilles"}
funk.FlatMap ............
Manipulates an iteratee (map, slice) and transforms it to to a flattened collection of another type:
- map -> slice
- slice -> slice
.. code-block:: go
r := funk.FlatMap([][]int{{1, 2}, {3, 4}}, func(x []int) []int {
return append(x, 0)
}) // []int{1, 2, 0, 3, 4, 0}
mapping := map[string][]int{
"Florent": {1, 2},
"Gilles": {3, 4},
}
r = funk.FlatMap(mapping, func(k string, v []int) []int {
return v
}) // []int{1, 2, 3, 4}
funk.Get ........
Retrieves the value at path of struct(s) or map(s).
.. code-block:: go
var bar *Bar = &Bar{
Name: "Test",
Bars: []*Bar{
&Bar{
Name: "Level1-1",
Bar: &Bar{
Name: "Level2-1",
},
},
&Bar{
Name: "Level1-2",
Bar: &Bar{
Name: "Level2-2",
},
},
},
}
var foo *Foo = &Foo{
ID: 1,
FirstName: "Dark",
LastName: "Vador",
Age: 30,
Bar: bar,
Bars: []*Bar{
bar,
bar,
},
}
funk.Get([]*Foo{foo}, "Bar.Bars.Bar.Name") // []string{"Level2-1", "Level2-2"}
funk.Get(foo, "Bar.Bars.Bar.Name") // []string{"Level2-1", "Level2-2"}
funk.Get(foo, "Bar.Name") // Test
funk.Get
also support map
values:
.. code-block:: go
bar := map[string]interface{}{
"Name": "Test",
}
foo1 := map[string]interface{}{
"ID": 1,
"FirstName": "Dark",
"LastName": "Vador",
"Age": 30,
"Bar": bar,
}
foo2 := &map[string]interface{}{
"ID": 1,
"FirstName": "Dark",
"LastName": "Vador",
"Age": 30,
"Labels": map[string]interface{} {
"example.com/hello": "world",
},
} // foo2.Bar is nil
funk.Get(bar, "Name") // "Test"
funk.Get([]map[string]interface{}{foo1, foo2}, "Bar.Name") // []string{"Test"}
funk.Get(foo2, "Bar.Name") // nil
funk.Get(foo2, `Labels."example.com/hello"`) // world
funk.Get
also handles nil
values:
.. code-block:: go
bar := &Bar{
Name: "Test",
}
foo1 := &Foo{
ID: 1,
FirstName: "Dark",
LastName: "Vador",
Age: 30,
Bar: bar,
}
foo2 := &Foo{
ID: 1,
FirstName: "Dark",
LastName: "Vador",
Age: 30,
} // foo2.Bar is nil
funk.Get([]*Foo{foo1, foo2}, "Bar.Name") // []string{"Test"}
funk.Get(foo2, "Bar.Name") // nil
funk.GetOrElse ..............
Retrieves the value of the pointer or default.
.. code-block:: go
str := "hello world"
GetOrElse(&str, "foobar") // string{"hello world"}
GetOrElse(str, "foobar") // string{"hello world"}
GetOrElse(nil, "foobar") // string{"foobar"}
funk.Set ........ Set value at a path of a struct
.. code-block:: go
var bar Bar = Bar{
Name: "level-0",
Bar: &Bar{
Name: "level-1",
Bars: []*Bar{
{Name: "level2-1"},
{Name: "level2-2"},
},
},
}
_ = Set(&bar, "level-0-new", "Name")
fmt.Println(bar.Name) // "level-0-new"
MustSet(&bar, "level-1-new", "Bar.Name")
fmt.Println(bar.Bar.Name) // "level-1-new"
Set(&bar, "level-2-new", "Bar.Bars.Name")
fmt.Println(bar.Bar.Bars[0].Name) // "level-2-new"
fmt.Println(bar.Bar.Bars[1].Name) // "level-2-new"
funk.MustSet ............ Short hand for funk.Set if struct does not contain interface{} field type to discard errors.
funk.Prune .......... Copy a struct with only selected fields. Slice is handled by pruning all elements.
.. code-block:: go
bar := &Bar{
Name: "Test",
}
foo1 := &Foo{
ID: 1,
FirstName: "Dark",
LastName: "Vador",
Bar: bar,
}
pruned, _ := Prune(foo1, []string{"FirstName", "Bar.Name"})
// *Foo{
// ID: 0,
// FirstName: "Dark",
// LastName: "",
// Bar: &Bar{Name: "Test},
// }
funk.PruneByTag .......... Same functionality as funk.Prune, but uses struct tags instead of struct field names.
funk.Keys .........
Creates an array of the own enumerable map keys or struct field names.
.. code-block:: go
funk.Keys(map[string]int{"one": 1, "two": 2}) // []string{"one", "two"} (iteration order is not guaranteed)
foo := &Foo{
ID: 1,
FirstName: "Dark",
LastName: "Vador",
Age: 30,
}
funk.Keys(foo) // []string{"ID", "FirstName", "LastName", "Age"} (iteration order is not guaranteed)
funk.Values ...........
Creates an array of the own enumerable map values or struct field values.
.. code-block:: go
funk.Values(map[string]int{"one": 1, "two": 2}) // []int{1, 2} (iteration order is not guaranteed)
foo := &Foo{
ID: 1,
FirstName: "Dark",
LastName: "Vador",
Age: 30,
}
funk.Values(foo) // []interface{}{1, "Dark", "Vador", 30} (iteration order is not guaranteed)
funk.ForEach ............
Range over an iteratee (map, slice).
Or update element in slice(Not map, reflect#Value#MapIndex#CanSet is false).
.. code-block:: go
funk.ForEach([]int{1, 2, 3, 4}, func(x int) {
fmt.Println(x)
})
foo := []int{1,2,3}
funk.ForEach(foo, func(x *int){ *x = *x * 2})
fmt.Println(foo) // []int{2, 4, 6}
funk.ForEachRight ............
Range over an iteratee (map, slice) from the right.
.. code-block:: go
results := []int{}
funk.ForEachRight([]int{1, 2, 3, 4}, func(x int) {
results = append(results, x)
})
fmt.Println(results) // []int{4, 3, 2, 1}
funk.Chunk ..........
Creates an array of elements split into groups with the length of the size. If array can't be split evenly, the final chunk will be the remaining element.
.. code-block:: go
funk.Chunk([]int{1, 2, 3, 4, 5}, 2) // [][]int{[]int{1, 2}, []int{3, 4}, []int{5}}
funk.FlattenDeep ................
Recursively flattens an array.
.. code-block:: go
funk.FlattenDeep([][]int{[]int{1, 2}, []int{3, 4}}) // []int{1, 2, 3, 4}
funk.Uniq .........
Creates an array with unique values.
.. code-block:: go
funk.Uniq([]int{0, 1, 1, 2, 3, 0, 0, 12}) // []int{0, 1, 2, 3, 12}
see also, typesafe implementations: UniqInt_, UniqInt64_, UniqFloat32_, UniqFloat64_, UniqString_
.. _UniqFloat32: https://godoc.org/github.com/thoas/go-funk#UniqFloat32 .. _UniqFloat64: https://godoc.org/github.com/thoas/go-funk#UniqFloat64 .. _UniqInt: https://godoc.org/github.com/thoas/go-funk#UniqInt .. _UniqInt64: https://godoc.org/github.com/thoas/go-funk#UniqInt64 .. _UniqString: https://godoc.org/github.com/thoas/go-funk#UniqString
funk.UniqBy .........
Creates an array with unique values returned by a callback.
.. code-block:: go
funk.UniqBy([]int{0, 1, 1, 2, 3, 0, 0, 12}, func(nbr int) int {
return nbr % 3
}) // []int{0, 1, 2}
foo1 := Foo{
ID: 42,
FirstName: "Bob",
}
foo2 := Foo{
ID: 42,
FirstName: "Bob",
}
funk.UniqBy([]Foo{foo1, foo2}, func(f Foo) int {
return f.ID
}) // []Foo{ Foo{ID: 42, Firstname: "Bob"} }
funk.Drop .........
Creates an array/slice with n
elements dropped from the beginning.
.. code-block:: go
funk.Drop([]int{0, 0, 0, 0}, 3) // []int{0}
see also, typesafe implementations: DropInt_, DropInt32_, DropInt64_, DropFloat32_, DropFloat64_, DropString_
.. _DropInt: https://godoc.org/github.com/thoas/go-funk#DropInt .. _DropInt32: https://godoc.org/github.com/thoas/go-funk#DropInt64 .. _DropInt64: https://godoc.org/github.com/thoas/go-funk#DropInt64 .. _DropFloat32: https://godoc.org/github.com/thoas/go-funk#DropFloat32 .. _DropFloat64: https://godoc.org/github.com/thoas/go-funk#DropFloat64 .. _DropString: https://godoc.org/github.com/thoas/go-funk#DropString
funk.Initial ............
Gets all but the last element of array.
.. code-block:: go
funk.Initial([]int{0, 1, 2, 3, 4}) // []int{0, 1, 2, 3}
funk.Tail .........
Gets all but the first element of array.
.. code-block:: go
funk.Tail([]int{0, 1, 2, 3, 4}) // []int{1, 2, 3, 4}
funk.Shuffle ............
Creates an array of shuffled values.
.. code-block:: go
funk.Shuffle([]int{0, 1, 2, 3, 4}) // []int{2, 1, 3, 4, 0}
see also, typesafe implementations: ShuffleInt_, ShuffleInt64_, ShuffleFloat32_, ShuffleFloat64_, ShuffleString_
.. _ShuffleFloat32: https://godoc.org/github.com/thoas/go-funk#ShuffleFloat32 .. _ShuffleFloat64: https://godoc.org/github.com/thoas/go-funk#ShuffleFloat64 .. _ShuffleInt: https://godoc.org/github.com/thoas/go-funk#ShuffleInt .. _ShuffleInt64: https://godoc.org/github.com/thoas/go-funk#ShuffleInt64 .. _ShuffleString: https://godoc.org/github.com/thoas/go-funk#ShuffleString
funk.Subtract .............
Returns the subtraction between two collections. It preserve order.
.. code-block:: go
funk.Subtract([]int{0, 1, 2, 3, 4}, []int{0, 4}) // []int{1, 2, 3}
funk.Subtract([]int{0, 3, 2, 3, 4}, []int{0, 4}) // []int{3, 2, 3}
see also, typesafe implementations: SubtractString_
.. SubtractString: https://godoc.org/github.com/thoas/go-funk#SubtractString
funk.Sum ........
Computes the sum of the values in an array.
.. code-block:: go
funk.Sum([]int{0, 1, 2, 3, 4}) // 10.0
funk.Sum([]interface{}{0.5, 1, 2, 3, 4}) // 10.5
see also, typesafe implementations: SumInt_, SumInt64_, SumFloat32_, SumFloat64_
.. _SumFloat32: https://godoc.org/github.com/thoas/go-funk#SumFloat32 .. _SumFloat64: https://godoc.org/github.com/thoas/go-funk#SumFloat64 .. _SumInt: https://godoc.org/github.com/thoas/go-funk#SumInt .. _SumInt64: https://godoc.org/github.com/thoas/go-funk#SumInt64
funk.Reverse ............
Transforms an array such that the first element will become the last, the second element will become the second to last, etc.
.. code-block:: go
funk.Reverse([]int{0, 1, 2, 3, 4}) // []int{4, 3, 2, 1, 0}
see also, typesafe implementations: ReverseInt_, ReverseInt64_, ReverseFloat32_, ReverseFloat64_, ReverseString_, ReverseStrings_
.. _ReverseFloat32: https://godoc.org/github.com/thoas/go-funk#ReverseFloat32 .. _ReverseFloat64: https://godoc.org/github.com/thoas/go-funk#ReverseFloat64 .. _ReverseInt: https://godoc.org/github.com/thoas/go-funk#ReverseInt .. _ReverseInt64: https://godoc.org/github.com/thoas/go-funk#ReverseInt64 .. _ReverseString: https://godoc.org/github.com/thoas/go-funk#ReverseString .. _ReverseStrings: https://godoc.org/github.com/thoas/go-funk#ReverseStrings
funk.SliceOf ............
Returns a slice based on an element.
.. code-block:: go
funk.SliceOf(f) // will return a []*Foo{f}
funk.RandomInt ..............
Generates a random int, based on a min and max values.
.. code-block:: go
funk.RandomInt(0, 100) // will be between 0 and 100
funk.RandomString .................
Generates a random string with a fixed length.
.. code-block:: go
funk.RandomString(4) // will be a string of 4 random characters
funk.Shard ..........
Generates a sharded string with a fixed length and depth.
.. code-block:: go
funk.Shard("e89d66bdfdd4dd26b682cc77e23a86eb", 1, 2, false) // []string{"e", "8", "e89d66bdfdd4dd26b682cc77e23a86eb"}
funk.Shard("e89d66bdfdd4dd26b682cc77e23a86eb", 2, 2, false) // []string{"e8", "9d", "e89d66bdfdd4dd26b682cc77e23a86eb"}
funk.Shard("e89d66bdfdd4dd26b682cc77e23a86eb", 2, 3, true) // []string{"e8", "9d", "66", "bdfdd4dd26b682cc77e23a86eb"}
funk.Subset .............
Returns true if a collection is a subset of another
.. code-block:: go
funk.Subset([]int{1, 2, 4}, []int{1, 2, 3, 4, 5}) // true
funk.Subset([]string{"foo", "bar"},[]string{"foo", "bar", "hello", "bar", "hi"}) //true
Performance
go-funk
currently has an open issue about performance_, don't hesitate to participate in the discussion
to enhance the generic helpers implementations.
Let's stop beating around the bush, a typesafe implementation in pure Go of funk.Contains
, let's say for example:
.. code-block:: go
func ContainsInt(s []int, e int) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
will always outperform an implementation based on reflect_ in terms of speed and allocs because of how it's implemented in the language.
If you want a similarity, gorm_ will always be slower than sqlx_ (which is very low level btw) and will use more allocs.
You must not think generic helpers of go-funk
as a replacement when you are dealing with performance in your codebase,
you should use typesafe implementations instead.
Contributing
- Ping me on twitter
@thoas <https://twitter.com/thoas>
_ (DMs, mentions, whatever :)) - Fork the
project <https://github.com/thoas/go-funk>
_ - Fix
open issues <https://github.com/thoas/go-funk/issues>
_ or request new features
Don't hesitate ;)
Authors
- Florent Messa
- Gilles Fabio
- Alexey Pokhozhaev
- Alexandre Nicolaie
.. _reflect: https://golang.org/pkg/reflect/ .. _lodash: https://lodash.com/ .. _performance: https://github.com/thoas/go-funk/issues/19 .. _gorm: https://github.com/jinzhu/gorm .. _sqlx: https://github.com/jmoiron/sqlx .. _godoc: https://godoc.org/github.com/thoas/go-funk
Top Related Projects
💥 A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find...)
🍕 Enjoy a slice! A utility library for dealing with slices and maps that focuses on type safety and performance.
A collection of generic data structures written in Go.
.NET LINQ capabilities in Go
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot