Awesome Go

gofn

CategoryUtilities
SubcategoryUtilities
Stars54

High performance utility functions written using Generics for Go 1.18+

About gofn

This large README is shown as a plain-text preview. Read the full README at the source


[![Go Version][gover-img]][gover] [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![GoReport][rpt-img]][rpt]

# gofn - Utility functions for Go

This is a collection of generics utility functions for Go 1.20+.

## Functionalities

`gofn` consists of useful and convenient functions for most common needs when working on slices, maps, structs, transformation, conversion, and so on.

Check out my other libs:
- [go-deepcopy](https://github.com/tiendc/go-deepcopy): True deep copy function
- [go-validator](https://github.com/tiendc/go-validator): Validation library
- [go-apperrors](https://github.com/tiendc/go-apperrors): Manipulating application errors
- [go-csvlib](https://github.com/tiendc/go-csvlib): High-level rich functionality CSV encoding and decoding library

## Installation

```shell
go get github.com/tiendc/gofn
```

## Function list

**Slice**
  - [Equal / EqualBy](#equal--equalby)
  - [ContentEqual / ContentEqualBy](#contentequal--contentequalby)
  - [Sort / IsSorted](#sort--issorted)
  - [RemoveAt](#removeat)
  - [FastRemoveAt](#fastremoveat)
  - [Remove](#remove)
  - [FastRemove](#fastremove)
  - [RemoveLastOf](#removelastof)
  - [FastRemoveLastOf](#fastremovelastof)
  - [RemoveAll](#removeall)
  - [Replace / ReplaceN / ReplaceAll](#replace--replacen--replaceall)
  - [Splice / SpliceEx](#splice--spliceex)
  - [Concat](#concat)
  - [Fill](#fill)
  - [SliceByRange](#slicebyrange)
  - [First / FirstOr](#first--firstor)
  - [Last / LastOr](#last--lastor)

**Slice searching**
  - [Contain](#contain--containby)
  - [ContainAll](#containall)
  - [ContainAny](#containany)
  - [Find / FindEx](#find--findex)
  - [FindLast / FindLastEx](#findlast--findlastex)
  - [IndexOf / IndexOfBy](#indexof--indexofby)
  - [LastIndexOf / LastIndexOfBy](#lastindexof--lastindexofby)
  - [CountValue / CountValueBy](#countvalue--countvalueby)

**Slice filtering**
  - [Filter](#filter)
  - [FilterNE](#filter)
  - [FilterLT / FilterLTE](#filter)
  - [FilterGT / FilterGTE](#filter)
  - [FilterRange](#filter)
  - [FilterIN / FilterNIN](#filter)
  - [FilterLIKE / FilterILIKE](#filter)

**Slice iteration**
  - [ForEach / ForEachReverse](#foreach--foreachreverse)
  - [Iter / IterReverse](#iter--iterreverse)

**Slice uniqueness**
  - [IsUnique / IsUniqueBy](#isunique--isuniqueby)
  - [FindUniques / FindUniquesBy](#finduniques--finduniquesby)
  - [FindDuplicates / FindDuplicatesBy](#findduplicates--findduplicatesby)
  - [ToSet / ToSetBy / ToSetByReverse ](#toset--tosetby--tosetbyreverse)

**Slice transformation**
  - [MapSlice / MapSliceEx](#mapslice--mapsliceex)
  - [MapSliceToMap / MapSliceToMapEx](#mapslicetomap--mapslicetomapex)
  - [MapSliceToMapKeys](#mapslicetomapkeys)

**Slice algo**
  - [Compact](#compact)
  - [Drop](#drop)
  - [Reverse / ReverseCopy](#reverse--reversecopy)
  - [Shuffle](#shuffle)
  - [Chunk / ChunkByPieces](#chunk--chunkbypieces)
  - [Union / UnionBy](#union--unionby)
  - [Intersection / IntersectionBy](#intersection--intersectionby)
  - [Difference / DifferenceBy](#difference--differenceby)
  - [Reduce / ReduceEx](#reduce--reduceex)
  - [ReduceReverse / ReduceReverseEx](#reducereverse--reducereverseex)
  - [Partition / PartitionN](#partition--partitionn)
  - [Flatten / Flatten3](#flatten--flatten3)
  - [Zip / Zip\<N\>](#zip--zipn)

**Slice conversion**
  - [ToIfaceSlice](#toifaceslice)
  - [ToStringSlice](#tostringslice)
  - [ToNumberSlice](#tonumberslice)
  - [ToSlice](#toslice)
  - [ToSliceSkippingNil / ToSliceSkippingZero](#tosliceskippingnil--tosliceskippingzero)
  - [ToPtrSlice](#toptrslice)

**Slice subset**
  - [ContainSlice](#containslice)
  - [IndexOfSlice](#indexofslice)
  - [LastIndexOfSlice](#lastindexofslice)
  - [SubSlice](#subslice)

**Map**
  - [MapEqual / MapEqualBy](#mapequal--mapequalby)
  - [MapContainKeys](#mapcontainkeys)
  - [MapContainValues](#mapcontainvalues)
  - [MapIter](#mapiter)
  - [MapKeys](#mapkeys)
  - [MapValues](#mapvalues)
  - [MapEntries](#mapentries)
  - [MapGet](#mapget)
  - [MapPop](#mappop)
  - [MapSetDefault](#mapsetdefault)
  - [MapUpdate / MapUpdateExistingOnly / MapUpdateNewOnly](#mapupdate--mapupdateexistingonly--mapupdatenewonly)
  - [MapCopy](#mapcopy)
  - [MapPick](#mappick)
  - [MapOmit](#mapomit)
  - [MapOmitCopy](#mapomitcopy)
  - [MapReverse](#mapreverse)

**Struct**
  - [StructToMap](#structtomap)
  - [ParseTag / ParseTagOf / ParseTagsOf](#parsetag--parsetagof--parsetagsof)

**String**
  - [RuneLength](#runelength)
  - [RandString / RandStringEx](#randstring--randstringex)
  - [StringSplit / StringSplitN](#stringsplit--stringsplitn)
  - [StringJoin / StringJoinEx / StringJoinBy](#stringjoin--stringjoinex--stringjoinby)
  - [StringLexJoin / StringLexJoinEx](#stringlexjoin--stringlexjoinex)
  - [StringWrap / StringUnwrap](#stringwrap--stringunwrap)
  - [StringToUpper1stLetter / StringToLower1stLetter](#stringtoupper1stletter--stringtolower1stletter)

**Number**
  - [ParseInt / ParseUint / ParseFloat](#parseint--parseuint--parsefloat)
  - [FormatInt / FormatUint / FormatFloat](#formatint--formatuint--formatfloat)
  - [NumberFmtGroup](#numberfmtgroup)
  - [ToSafeInt\<N\> / ToSafeUint\<N\>](#tosafeintn--tosafeuintn)

**Time**
  - [MinTime / MaxTime / MinMaxTime](#mintime--maxtime--minmaxtime)
  - [ExecDuration / ExecDurationN](#execduration--execdurationn)
  - [ExecDelay](#execdelay)

**Math**
  - [All](#all)
  - [Any](#any)
  - [Abs](#abs)
  - [Clamp](#clamp)
  - [Min / Max / MinMax](#min--max--minmax)
  - [Sum / SumAs](#sum--sumas)
  - [Product / ProductAs](#product--productas)

**Concurrency**
  - [ExecTasks / ExecTasksEx](#exectasks--exectasksex)
  - [ExecTaskFunc / ExecTaskFuncEx](#exectaskfunc--exectaskfuncex)

**Function**
  - [Bind\<N\>Arg\<M\>Ret ](#bindnargmret)
  - [Partial\<N\>Arg\<M\>Ret ](#partialnargmret)

**Execute Retry**
- [ExecRetry / ExecRetryN](#execretry--execretryn)
- [ExecRetryCtx / ExecRetryCtxN](#execretryctx--execretryctxn)

**Randomization**
  - [RandChoice](#randchoice)
  - [RandChoiceMaker](#randchoicemaker)
  - [RandToken / RandTokenAsHex](#randtoken--randtokenashex)

**Error handling**
  - [ErrWrap / ErrWrapL](#errwrap--errwrapl)
  - [ErrUnwrap](#errunwrap)
  - [ErrUnwrapToRoot](#errunwraptoroot)

**Utility**
  - [FirstNonEmpty](#firstnonempty)
  - [Coalesce](#coalesce)
  - [If](#if)
  - [Must\<N\>](#mustn)
  - [ToPtr](#toptr)
  - [PtrValueOrEmpty](#ptrvalueorempty)
  - [Head](#head)
  - [Tail](#tail)


### Slice
---
 
#### Equal / EqualBy

Returns true if 2 slices have the same size and all elements of them equal in the current order.

```go
Equal([]int{1, 2, 3}, []int{1, 2, 3}) // true
Equal([]int{1, 2, 3}, []int{3, 2, 1}) // false

// Use EqualBy for custom equal comparison
EqualBy([]string{"one", "TWO"}, []string{"ONE", "two"}, strings.EqualFold) // true
```
 
#### ContentEqual / ContentEqualBy

Returns true if 2 slices have the same size and contents equal regardless of the order of elements.

```go
ContentEqual([]int{1, 2, 3}, []int{2, 1, 3})       // true
ContentEqual([]int{1, 2, 2, 3}, []int{2, 1, 3})    // false
ContentEqual([]int{1, 2, 2, 3}, []int{2, 1, 2, 3}) // true
ContentEqual([]int{1, 2, 2, 3}, []int{1, 1, 2, 3}) // false

// Use ContentEqualBy for custom key function
ContentEqualBy([]string{"one", "TWO"}, []string{"two", "ONE"}, strings.ToLower) // true
```

#### RemoveAt

Removes element at the specified index.

```go
s := []int{1, 2, 3}
RemoveAt(&s, 1) // s == []int{1, 3}
```

#### FastRemoveAt

Removes element at the specified index by swapping it with the last element of the slice.
This function is fast as it doesn't cause copying of slice content.

```go
s := []int{1, 2, 3, 4}
FastRemoveAt(&s, 1) // s == []int{1, 4, 3} (2 and 4 are exchanged)
```
 
#### Sort / IsSorted
 
Convenient wrappers of the built-in `sort.Slice`.

```go
Sort([]int{1, 3, 2})         // []int{1, 2, 3}
SortDesc([]int{1, 3, 2})     // []int{3, 2, 1}
IsSorted([]int{1, 3, 2})     // false
IsSortedDesc([]int{3, 2, 1}) // true
```

#### Remove

Removes a value from a slice.

```go
s := []int{1, 2, 3}
Remove(&s, 1) // s == []int{2, 3}
```

#### FastRemove

Removes a value from a slice by swapping it with the last element of the slice.

```go
s := []int{1, 2, 3, 4}
FastRemove(&s, 2) // s == []int{1, 4, 3} (2 and 4 are exchanged)
```

#### RemoveLastOf

Removes last occurrence of a value from a slice.

```go
s := []int{1, 2, 1, 3}
RemoveLastOf(&s, 1) // s == []int{1, 2, 3}
```

#### FastRemoveLastOf

Removes last occurrence of a value from a slice by swapping it with the last element of the slice.

```go
s := []int{1, 2, 1, 3, 4}
FastRemoveLastOf(&s, 1) // s == []int{1, 2, 4, 3} (1 and 4 are exchanged)
```

#### RemoveAll

Removes all occurrences of a value from a slice.

```go
s := []int{1, 2, 1, 3, 1}
RemoveAll(&s, 1) // s == []int{2, 3}
```

#### Replace / ReplaceN / ReplaceAll

Replaces a value with another value.

```go
// Replaces first occurrence of the value
Replace([]int{1, 2, 1, 3, 1}, 1, 11)     // []int{11, 2, 1, 3, 1}
// Replaces first n occurrences of the value (use -1 to replace all)
ReplaceN([]int{1, 2, 1, 3, 1}, 1, 11, 2) // []int{11, 2, 11, 3, 1}
// Replaces all occurrences of the value
ReplaceAll([]int{1, 2, 1, 3, 1}, 1, 11)  // []int{11, 2, 11, 3, 11}
```

#### Splice / SpliceEx

Removes a portion of the given slice and inserts elements of another slice into that position.

Usage: `Splice(s []T, start int, deleteCount int, insertingElements ...T)`.
If `start < -len(s)`, `0` is used.
If `-len(s) <= start < 0`, `start + len(s)` is used.
If `start >= len(s)`, no element will be deleted, but the new elements are still added to the end.
If `deleteCount <= 0`, no elements will be removed.

```go
s := Splice([]int{1, 2, 3}, 1, 1, 100)         // s == []int{1, 100, 3}
s := Splice([]int{1, 2, 3}, 1, 0, 100)         // s == []int{1, 100, 2, 3}
s := Splice([]int{1, 2, 3}, 1, 1, 100, 101)    // s == []int{1, 100, 101, 3}
s := Splice([]int{1, 2, 3}, 0, 2, 100, 101)    // s == []int{100, 101, 3}

// Use SpliceEx to get deleted items as the 2nd returning value
s, delItems := SpliceEx([]int{1, 2, 3}, 1, 1, 100)        // s == []int{1, 100, 3}, delItems == []int{2}
s, delItems := SpliceEx([]int{1, 2, 3}, 1, 0, 100)        // s == []int{1, 100, 2, 3}, delItems == []int{}
s, delItems := SpliceEx([]int{1, 2, 3}, 1, 1, 100, 101)   // s == []int{1, 100, 101, 3}, delItems == []int{2}
s, delItems := SpliceEx([]int{1, 2, 3}, 0, 2, 100, 101)   // s == []int{100, 101, 3}, delItems == []int{1, 2}
```

#### Concat
 
Concatenates two or more slices.

```go
Concat([]int{1}, []int{2}, []int{2, 3}) // []int{1, 2, 2, 3}
```

#### Fill

Fills a slice with specified value.

```go
s := make([]int, 5)
Fill(s, 1)  // s == []int{1, 1, 1, 1, 1}

s2 := s[2:4]
Fill(s2, 1) // s2 == []int{1, 1}, s == []int{0, 0, 1, 1, 0}
```

#### First / FirstOr

Returns the first element of slice.

```go
First([]int{1, 2, 3})      // 1, true
First([]string{})          // "", false

// Return the default value if slice is empty
FirstOr([]int{1, 2, 3}, 4) // 1
FirstOr([]int{}, 11)       // 11
```

#### Last / LastOr

Returns the last element of slice.

```go
Last([]int{1, 2, 3})       // 3, true
Last([]string{})           // "", false

// Return the default value if slice is empty
LastOr([]int{1, 2, 3}, 4)  // 3
LastOr([]int{}, 11)        // 11
```

#### SliceByRange

Generates a slice for the given range.

```go
s := SliceByRange(0, 5, 1)         // []int{0, 1, 2, 3, 4}
s := SliceByRange(0.0, 5, 2)       // []float64{0, 2, 4}
s := SliceByRange(int32(5), 0, -2) // []int32{5, 3, 1}
```
 
### Slice searching
---

#### Contain / ContainBy

Returns true if a slice contains a value.

```go
Contain([]int{1, 2, 3}, 2) // true
Contain([]int{1, 2, 3}, 0) // false

// Use ContainBy for custom function
ContainBy([]string{"one", "TWO"}, func(elem string) bool {
    return strings.ToLower(elem) == "two"
}) // true
```

#### ContainAll

Returns true if a slice contains all given values.

```go
ContainAll([]int{1, 2, 3, 4, 5}, 2, 4, 3) // true
ContainAll([]int{1, 2, 3, 4, 5}, 2, 7)    // false
```

#### ContainAny

Returns true if a slice contains any of the given values.

```go
ContainAny([]int{1, 2, 3, 4, 5}, 2, 4, 7) // true
ContainAny([]int{1, 2, 3, 4, 5}, 7, 8, 9) // false
```
 
#### Find / FindEx

Finds a value in a slice.

```go
v, found := Find([]string{"one", "TWO"}, func(elem string) bool {
    return strings.ToLower(elem) == "two"
}) // v == "TWO", found == true

// FindEx lets the given function decide which value to return
type Person struct {
    Name string
    Age  int
}
// Finds age of person having name "Tim"
ageOfTim, found := FindEx([]Person{{"John", 40}, {"Tim", 50}}, func(p Person) (int, bool) {
    return p.Age, p.Name == "Tim"
}) // ageOfTim == 50, found == true
```

#### FindLast / FindLastEx

Finds a value in a slice from the end.

```go
v, found := FindLast([]string{"one", "TWO", "ONe"}, func(elem string) bool {
    return strings.ToLower(elem) == "one"
}) // v == "ONe", found == true

// FindLastEx lets the given function decide which value to return
type Person struct {
    Name string
    Age  int
}
// Finds age of the last person having name "tim"
ageOfTim, found := FindLastEx([]Person{{"John", 40}, {"Tim", 50}, {"TIM", 60}}, func(p Person) (int, bool) {
    return p.Age, strings.ToLower(p.Name) == "tim"
}) // ageOfTim == 60, found == true
```

#### IndexOf / IndexOfBy

Finds the index of a value in a slice, returns -1 if not found.

```go
IndexOf([]int{1, 2, 3}, 4) // -1
IndexOf([]int{1, 2, 3}, 2) // 1

// Use IndexOfBy for custom function
IndexOfBy([]string{"one", "TWO"}, func(elem string) bool {
    return strings.ToLower(elem) == "two"
}) // 1
```

#### LastIndexOf / LastIndexOfBy

Finds the last index of an element in a slice, returns -1 if not found.

```go
LastIndexOf([]int{1, 2, 3}, 4)    // -1
LastIndexOf([]int{1, 2, 1, 3}, 1) // 2
```
 
#### CountValue / CountValueBy

Counts the number of occurrences of a value in a slice.

```go
CountValue([]int{1, 2, 3}, 4)    // 0
CountValue([]int{1, 2, 3, 2}, 2) // 2
```

### Slice filtering
---

#### Filter

Filters a slice with condition.

```go
Filter([]int{1, 2, 3, 4}, func (i int) bool {
    return i % 2 == 0
}) // []int{2, 4}

FilterLT([]int{1, 2, 3, 4}, 3)        // []int{1, 2}
FilterLTE([]int{1, 2, 3, 4}, 3)       // []int{1, 2, 3}
FilterGT([]int{1, 2, 3, 4}, 3)        // []int{4}
FilterGTE([]int{1, 2, 3, 4}, 3)       // []int{3, 4}
FilterRange([]int{1, 2, -2, 4}, 0, 3) // []int{1, 2}
FilterNE([]int{1, 2, 3, 4}, 3)        // []int{1, 2, 4}
FilterIN([]int{1, 2, 3, 4}, 3, 2, 7)  // []int{2, 3}
FilterNIN([]int{1, 2, 3, 4}, 3, 2, 7) // []int{1, 4}
FilterLIKE([]string{"*Abc*", "*abc*", "abc*", "*abc"}, "Abc")  // []string{"*Abc*"}
FilterILIKE([]string{"*Abc*", "*abc*", "abc*", "*abc"}, "Abc") // []string{"*Abc*", "*abc*", "abc*", "*abc"}
```

### Slice iteration
---

#### ForEach / ForEachReverse

Iterates over slice content.

```go
ForEach([]int{1, 2, 3}, func (i, v int) {
    fmt.Printf("%d ", v)
}) // prints 1 2 3

ForEachReverse([]int{1, 2, 3}, func (i, v int) {
    fmt.Printf("%d ", v)
}) // prints 3 2 1

// ForEachPtr can be faster if you iterate over a slice of big structs
ForEachPtr([]BigStruct{...}, func (i, v *BigStruct) { ... })
ForEachPtrReverse([]BigStruct{...}, func (i, v *BigStruct) { ... })
```

#### Iter / IterReverse

Iterates over one or multiple slices with ability to stop.

```go
Iter(func (i, v int) bool {
    fmt.Printf("%d ", v)
    return i < 3
}, []int{1, 2, 3}, []int{4, 5}) // prints 1 2 3 4

IterReverse(func (i, v int) bool {
    fmt.Printf("%d ", v)
    return true
}, []int{1, 2, 3}, []int{4, 5}) // prints 5 4 3 2 1

// IterPtr can be faster if you iterate over a slice of big structs
IterPtr(func (i, v *BigStruct) bool { ... }, []BigStruct{...})
IterPtrReverse(func (i, v *BigStruct) bool { ... }, []BigStruct{...})
```

### Slice uniqueness
---

#### IsUnique / IsUniqueBy

Returns true if a slice contains unique values.

```go
IsUnique([]int{1, 2, 3}) // true
IsUnique([]int{1, 2, 1}) // false

// Use IsUniqueBy for custom function
IsUniqueBy([]string{"one", "ONE"}, strings.ToLower) // false
```

#### FindUniques / FindUniquesBy

Finds all unique elements in the given slice. The order of elements in the result is the same
as they appear in the input.

```go
FindUniques([]int{1, 2, 3, 2})  // []int{1, 3}
FindUniques([]int{1, 2, 2, 1})  // []int{}

// FindUniquesBy supports custom key function
FindUniquesBy([]string{"one", "ONE", "Two"}, func (s string) string {
    return strings.ToLower(s)
}) // []string{"Two"}
```

#### FindDuplicates / FindDuplicatesBy

Finds all elements which are duplicated in the given slice. The order of elements in the result is the same
as they appear in the input.

```go
FindDuplicates([]int{1, 2, 3, 2})  // []int{2}
FindDuplicates([]int{1, 2, 3})     // []int{}

// FindDuplicatesBy supports custom key function
FindDuplicatesBy([]string{"one", "ONE", "Two"}, func (s string) string {
    return strings.ToLower(s)
}) // []string{"one"}
```

#### ToSet / ToSetBy / ToSetByReverse

Calculates unique values of a slice.

```go
ToSet([]int{1, 2, 3, 1, 2})        // []int{1, 2, 3}
ToSet([]string{"one", "2", "one"}) // []string{"one", "2"}

// Use ToSetBy for custom key function
ToSetBy([]string{"one", "TWO", "two", "One"}, strings.ToLower) // []string{"one", "TWO"}


// Use ToSetByReverse for iterating items from the end of the list
ToSetByReverse([]string{"one", "TWO", "two", "One"}, strings.ToLower) // []string{"One", "two"}
```

### Slice transformation
---

#### MapSlice / MapSliceEx

Transforms a slice to a slice.

```go
MapSlice([]string{"1", "2 ", " 3"}, strings.TrimSpace)   // []string{"1", "2", "3"}

// Use MapSliceEx to transform with error handling
MapSliceEx([]string{"1","2","3"}, gofn.ParseInt[int])    // []int{1, 2, 3}
MapSliceEx([]string{"1","x","3"}, gofn.ParseInt[int])    // strconv.ErrSyntax
MapSliceEx([]string{"1","200","3"}, gofn.ParseInt[int8]) // strconv.ErrRange
```

#### MapSliceToMap / MapSliceToMapEx

Transforms a slice to a map.

```go
MapSliceToMap([]int{1, 2, 3}, func (i int) (int, string) {
    return i, fmt.Sprintf("%d", i)
}) // map[int]string{1: "1", 2: "2", 3: "3"}

// Use MapSliceToMapEx to transform with error handling
MapSliceToMapEx([]string{"1","300","3"}, func (s string) (string, int, bool) {
    v, e := gofn.ParseInt[int8](s)
    return s, v, e
}) // strconv.ErrRange
```

#### MapSliceToMapKeys

Transforms a slice to a map with using slice items as map keys.

```go
MapSliceToMapKeys([]int{1, 2, 3, 2}, "x")     // map[int]string{1: "x", 2: "x", 3: "x"}
MapSliceToMapKeys([]int{1, 2, 1}, struct{}{}) // map[int]struct{}{1: struct{}{}, 2: struct{}{}}
```

### Slice algo
---

#### Compact

Compacts a slice by removing zero elements.  Not change the source slice.

```go
s := Compact([]int{1, 0, 3}) // s == []int{1, 3}
```

#### Reverse / ReverseCopy

Reverses slice content.

```go
Reverse([]int{1, 2, 3}) // []int{3, 2, 1}

s1 := []int{1, 2, 3}
s2 := ReverseCopy(s1)  // s1 == []int{1, 2, 3}, s2 == []int{3, 2, 1}
```

#### Drop

Returns a new slice with dropping values in the specified list.
NOTE: this function is just a call to `FilterNIN()`.

```go
Drop([]int{1, 2, 3, 4}, 3, 1) // []int{2, 4}
```

#### Shuffle

Shuffle items of a slice. Not change the source slice.

```go
s := Shuffle([]int{1, 2, 3}) // s is a new slice with random items of the input
```

#### Chunk / ChunkByPieces

Splits slice content into chunks.

```go
Chunk([]int{1, 2, 3, 4, 5}, 2)         // [][]int{[]int{1, 2}, []int{3, 4}, []int{5}}
ChunkByPieces([]int{1, 2, 3, 4, 5}, 2) // [][]int{[]int{1, 2, 3}, []int{4, 5}}
```

#### Union / UnionBy

Finds all unique values from multiple slices.

```go
Union([]int{1, 3, 2}, []int{1, 2, 2, 4}) // []int{1, 3, 2, 4}
```

#### Intersection / IntersectionBy

Finds all unique shared values from multiple slices.

```go
Intersection([]int{1, 3, 2}, []int{1, 2, 2, 4}) // []int{1, 2}
```

Frequently Asked Questions

What is gofn?

gofn is a Utilities library for the Go programming language. High performance utility functions written using Generics for Go 1.18+

How do I install gofn?

Install gofn with the Go module system using `go get tiendc/gofn`. Check the repository for the current installation instructions.

What category does gofn belong to?

gofn is listed under Utilities, specifically Utilities.

← Back to Utilities