Useful collection functions for golang, based on generic types

go-collection

English | 简体中文

go-collection provides developers with a convenient set of functions for working with common slices, maps, and arrays data. These functions are based on the generic types of Go 1.18, which makes it easier to use them without annoying type assertions. In addition to using these functions directly, it also supports method chaining.

collect.Reduce(collect.Filter(collect.Map([]int{1, 2, 3}, fn), fn), fn)

Equivalent to:

collect.UseSlice([]int{1, 2, 3}).Map(fn).Filter(fn).Reduce(fn)

Note: Since Go 1.18 has not yet been officially released and its language behavior may still change after the release, go-collection is currently for trial use only. If you have additional questions or suggestions, please file an issue.

Note: Go 1.18 Beta 2, released this past week, still has some bugs, so you will need to use the gotip tool to get the latest master branch of Go when trying out go-collection.

Installation

go get -u github.com/sxyazi/go-collection

Then import it

import collect "github.com/sxyazi/go-collection"

API

Its API is very simple and if you have used other similar packages, you should be able to get started with it in a few minutes. For convenience, they are described below in function form.

Slice

The corresponding chained function is collect.UseSlice()

  • Len gets the length of the slice

    Examples
    d1 := []int{1, 2, 3}
    collect.Len(d1) // 3
    
    d2 := []string{"a", "b", "c"}
    collect.Len(d2) // 3
  • Each iterates over each element in the slice

    Examples
    d := []float64{1, 2, 3}
    collect.Each(d, func(value float64, index int) {
      fmt.Println(index, value)
    })
  • Empty checks if the slice is empty

    Examples
    var d []int
    collect.Empty(d) // true
  • Same checks if the contents of two slices are the same

    Examples
    d1 := []int{1, 2, 3}
    d2 := []int{1, 2, 3}
    collect.Same(d1, d2) // true
    
    d3 := [][]int{{1, 2, 3}, {4, 5, 6}}
    d4 := [][]int{{1, 2, 3}, {4, 5, 6}}
    collect.Same(d3, d4) // true
  • First gets the first element of the slice

    Examples
    d1 := []int{1, 2, 3}
    value, ok := collect.First(d1) // 1, true
    
    var d2 []int
    value, ok = collect.First(d2) // 0, false
  • Last gets the last element of the slice

    Examples
    d1 := []int{1, 2, 3}
    value, ok := collect.Last(d1) // 3, true
    
    var d2 []int
    value, ok = collect.Last(d2) // 0, false
  • Index gets the index of the specified element in the slice, and returns -1 if it does not exist.

    Examples
    d1 := []int{1, 2, 3}
    collect.Index(d1, 2) // 1
    
    s1 := []string{"a", "b", "c"}
    s2 := []string{"d", "e", "f"}
    collect.Index([][]string{s1, s2}, s2) // 1
  • Contains checks if the slice contains the specified element

    Examples
    d1 := []int{1, 2, 3}
    collect.Contains(d1, 2) // true
    
    s1 := []string{"a", "b", "c"}
    s2 := []string{"d", "e", "f"}
    collect.Contains([][]string{s1, s2}, s2) // true
  • Diff computes the difference set of two slices

    Examples
    d := []int{1, 2, 3}
    collect.Diff(d, []int{2, 3})  // []int{1}
  • Filter filters the elements in the slice

    Examples
    collect.Filter([]int{1, 2, 3, 4, 5}, func(value, index int) bool {
      return value % 2 == 0
    })  // []int{2, 4}
  • Map iterates over and sets the value of the elements in the slice

    Examples
    collect.Map([]int{1, 2, 3}, func(value, index int) int {
      return value * 2
    })  // []int{2, 4, 6}
  • Unique removes duplicate elements from slices

    Examples
    d := []int{1, 2, 3, 3, 4}
    collect.Unique(d)  // []int{1, 2, 3, 4}
  • Merge merges the current slice with other slices

    Examples
    d1 := []int{1, 2}
    d2 := []int{3, 4}
    d3 := []int{5, 6}
    
    collect.Merge(d1, d2)      // []int{1, 2, 3, 4}
    collect.Merge(d1, d2, d3)  // []int{1, 2, 3, 4, 5, 6}
  • Random gets an element of the slice at random

    Examples
    d := []int{1, 2}
    value, ok := collect.Random(d)  // 1 or 2, true
    
    d := []int{}
    value, ok := collect.Random(d)  // 0, false
  • Reverse reverses the elements in a slice

    Examples
    d := []int{1, 2}
    collect.Reverse(d)  // []int{2, 1}
  • Shuffle randomly shuffles the elements in a slice

    Examples
    d := []int{1, 2}
    collect.Shuffle(d)  // []int{1, 2} or []int{2, 1}
  • Slice takes a segment from a slice

    Examples

    Function signature: Slice(items T, offset int)

    d := []int{1, 2, 3, 4}
    collect.Slice(d, 2)  // []int{3, 4}

    Function signature: Slice(items T, offset, length int)

    collect.Slice(d, 0, 2)  // []int{1, 2}
    collect.Slice(d, 2, 2)  // []int{3, 4}
  • Split splits a slice into multiple slices by the specified amount

    Examples
    d := []int{1, 2, 3, 4, 5}
    collect.Split(d, 2)  // [][]int{{1, 2}, {3, 4}, {5}}
  • Splice removes a segment from the slice

    Examples

    Function signature: Splice(items T, offset int)

    d := []int{1, 2, 3, 4, 5}
    collect.Splice(d, 2)  // []int{1, 2}

    Function signature: Splice(items T, offset, length int)

    d := []int{1, 2, 3, 4, 5}
    collect.Splice(d, 2, 2)  // []int{1, 2, 5}

    Function signature: Splice(items T, offset, length int, replacements ...T|E)

    d := []int{1, 2, 3, 4}
    collect.Splice(d, 1, 2, []int{22, 33})             // []int{1, 22, 33, 4}
    collect.Splice(d, 1, 2, 233, 333)                  // []int{1, 222, 333, 4}
    collect.Splice(d, 1, 2, []int{22}, 33, []int{44})  // []int{1, 22, 33, 44, 4}

    It is worth noting that the Splice method in the chain differs from the above in that it returns the deleted elements, and the result of the deletion occurs on the original collection:

    c1 := collect.UseSlice([]int{1, 2, 3, 4})
    c1.Splice(2)  // []int{3, 4}
    c1.All()      // []int{1, 2}
    
    c2 := collect.UseSlice([]int{1, 2, 3, 4})
    c2.Splice(1, 2, []int{22, 33})  // []int{2, 3}
    c2.All()                        // []int{1, 22, 33, 4}
  • Reduce reduces the collection to a single value, and the parameters of each iteration are the results of the previous iteration

    Examples
    collect.Reduce([]int{1, 2, 3}, 100, func(carry, value, key int) int {
    	return carry + value
    })  // 106
  • Count counts the number of occurrences of each element in the slice

    Examples
    d := []bool{true, true, false}
    collect.Count(d)  // map[bool]int{true: 2, false: 1}

Array

Exactly the same as slice, you just pass in the array converted to a slice:

arr := [3]int{1, 2, 3}

collect.Len(arr[:])
// or
collect.UseSlice(arr[:]).Len()

Map

The corresponding chained function is collect.UseMap()

  • Only gets the elements of the map with the specified keys

    Examples
    d := map[string]int{"a": 1, "b": 2, "c": 3}
    collect.Only(d, "a")       // map[string]int{"a": 1}
    collect.Only(d, "a", "b")  // map[string]int{"a": 1, "b": 2}
  • Except gets the elements of the map with the specified keys removed

    Examples
    d := map[string]int{"a": 1, "b": 2, "c": 3}
    collect.Except(d, "a")       // map[string]int{"b": 2, "c": 3}
    collect.Except(d, "a", "b")  // map[string]int{"c": 3}
  • Keys gets all the keys in the map

    Examples
    d := map[string]int{"a": 1, "b": 2, "c": 3}
    collect.Keys(d)  // []string{"a", "b", "c"}
  • DiffKeys compares with the given collection and returns the key/value pairs in the given collection that do not exist in the original collection

    Examples
    d1 := map[string]int{"a": 1, "b": 2, "c": 3}
    d2 := map[string]int{"b": 22, "c": 33}
    
    collect.DiffKeys(d1, d2)  // map[string]int{"a": 1}
  • Has checks if the map contains the specified key

    Examples
    d := map[string]int{"a": 1}
    collect.Has(d, "a")  // true
  • Set sets the value of the specified key in the map

    Examples
    d := map[string]int{"a": 1}
    collect.Set(d, "b", 2)  // map[string]int{"a": 1, "b": 2}
  • Get gets the value of the specified key in the map

    Examples
    d := map[string]int{"a": 1}
    
    value, ok := collect.Get(d, "a")  // 1, true
    value, ok := collect.Get(d, "b")  // 0, false
  • Merge merges the current map with other maps

    Examples
    d1 := map[string]int{"a": 1, "b": 2}
    d2 := map[string]int{"b": 22}
    d3 := map[string]int{"b": 222, "c": 3}
    
    collect.MapMerge(d1, d2)            // map[string]int{"a": 1, "b": 22}
    collect.UseMap(d1).Merge(d2).All()  // Equal to the above
    
    collect.MapMerge(d1, d2, d3)            // map[string]int{"a": 1, "b": 222, "c": 3}
    collect.UseMap(d1).Merge(d2, d3).All()  // Equal to the above
  • Union unites the current map with other maps, and the items in the original map are given priority

    Examples
    d1 := map[string]int{"a": 1, "b": 2}
    d2 := map[string]int{"b": 22, "c": 3}
    collect.Union(d1, d2)  // map[string]int{"a": 1, "b": 2, "c": 3}

Number slice

The corresponding chained function is collect.UseNumber(),which is a subset of slice and includes, in addition to all the methods of slice, the additional:

  • Sum calculates the sum

    Examples
    collect.Sum([]float64{1, 3.14})  // 4.14
  • Min calculates the minimum value

    Examples
    collect.Min([]int{0, 1, -3})  // -3
  • Max calculates the maximum value

    Examples
    collect.Max([]int{0, 1, -3})  // 1
  • Sort sorts the numbers in the collection in ascending order

    Examples
    collect.Sort([]float64{1, -4, 0, -4.3})  // []float64{-4.3, -4, 0, 1}
  • SortDesc sorts the numbers in the collection in descending order

    Examples
    collect.SortDesc([]float64{1, -4, 0, -4.3})  // []float64{1, 0, -4, -4.3}
  • Avg calculates the average

    Examples
    collect.Avg([]int{1, 2, 3, 4})  // 2.5
  • Median calculates the median

    Examples
    collect.Median([]int{1, 2, 3, 4})  // 2.5

Standalone functions

Due to Golang's support for generics, it is not possible to define generic types in methods, so only their function implementations (which do not support chain calls) are listed below:

  • AnyGet gets value of arbitrary types (slices, maps, arrays, structures, and pointers to these) in a non-strict form

    Examples
    m := map[string]int{"a": 1, "b": 2}
    collect.AnyGet[int](m, "b")  // 2
    
    u := &User{"Email": "[email protected]"}
    collect.AnyGet[string](u, "Email")  // [email protected]
    
    s := [][]int{{1, 2}, {3, 4}}
    collect.AnyGet[[]int](s, 1)  // []{3, 4}
  • Pluck retrieves all values for a given key. supports all values supported by AnyGet

    Examples
    d := []User{{ID: 33, Name: "Lucy"}, {ID: 193, Name: "Peter"}}
    collect.Pluck[int](d, "ID")  // int[]{33, 193}
  • MapPluck retrieves all values of a given key, only maps are supported

    Examples
    d := []map[string]int{{"ID": 33, "Score": 10}, {"ID": 193, "Score": 6}}
    collect.MapPluck(d, "ID")  // int[]{33, 193}
  • KeyBy retrieves a collection with the value of the given key as the identifier (if there are duplicate keys, only the last one will be kept). Supports all values supported by AnyGet

    Examples
    d := []User{{ID: 33, Name: "Lucy"}, {ID: 193, Name: "Peter"}, {ID: 194, Name: "Peter"}}
    collect.KeyBy[string](d, "Name")  // map[Lucy:{33 Lucy} Peter:{194 Peter}]
  • MapKeyBy retrieves the collection with the value of the given key as the identifier (if there are duplicate keys, only the last one will be kept), only maps are supported

    Examples
    d := []map[string]int{{"ID": 33, "Score": 6}, {"ID": 193, "Score": 10}, {"ID": 194, "Score": 10}}
    collect.MapKeyBy(d, "Score")  // map[6:map[ID:33 Score:6] 10:map[ID:194 Score:10]]
  • GroupBy groups the items in a collection using the value of the given key as the identifier. Supports all values supported by AnyGet

    Examples
    d := []User{{ID: 33, Name: "Lucy"}, {ID: 193, Name: "Peter"}, {ID: 194, Name: "Peter"}}
    collect.GroupBy[string](d, "Name")  // map[Lucy:[{33 Lucy}] Peter:[{193 Peter} {194 Peter}]]
  • MapGroupBy groups items in a collection using the value of the given key as the identifier, only maps are supported

    Examples
    d := []map[string]int{{"ID": 33, "Score": 6}, {"ID": 193, "Score": 10}, {"ID": 194, "Score": 10}}
    collect.MapGroupBy(d, "Score")  // map[6:[map[ID:33 Score:6]] 10:[map[ID:193 Score:10] map[ID:194 Score:10]]]
  • Times creates a new collection of slices by calling the callback with specified number of times

    Examples
    collect.Times(3, func(number int) float64 {
    	return float64(number) * 3.14
    })  // *SliceCollection{[]float64{3.14, 6.28, 9.42}}
  • SortBy calls a callback for each element and performs an ascending sort by the return value of the callback

    Examples
    collect.SortBy([]int{2, 1, 3}, func(item, index int) string {
    	return strconv.Itoa(item)
    })  // *SliceCollection{[]int{1, 2, 3}}
  • SortByDesc calls a callback for each element and performs a descending sort by the return value of the callback

    Examples
    collect.SortByDesc([]int{2, 1, 3}, func(item, index int) string {
    	return strconv.Itoa(item)
    })  // *SliceCollection{[]int{3, 2, 1}}

License

go-collection is MIT licensed.

Similar Resources

Subfinder is a subdomain discovery tool that discovers valid subdomains for websites. Designed as a passive framework to be useful for bug bounties and safe for penetration testing.

Subfinder is a subdomain discovery tool that discovers valid subdomains for websites. Designed as a passive framework to be useful for bug bounties and safe for penetration testing.

Fast passive subdomain enumeration tool. Features • Install • Usage • API Setup • License • Join Discord Subfinder is a subdomain discovery tool that

Jan 4, 2023

Multiplexer over TCP. Useful if target server only allows you to create limited tcp connections concurrently.

tcp-multiplexer Use it in front of target server and let your client programs connect it, if target server only allows you to create limited tcp conne

May 27, 2021

A quick and dirty but useful tool to download each text/html page from the wayback machine for a specific domain and search for keywords within the saved content

wayback-keyword-search A quick and dirty but useful tool to download each text/html page from the wayback machine for a specific domain and search for

Dec 2, 2022

simple and useful gorm's plugin

gorm-plugin ExplainPlugin Check if index is used when thresholdTime = sqlCostTime import ( "github.com/longlihale/gorm-plugin" ) DB.Use(gormplug

Dec 22, 2021

Go-http-sleep: Delayed response http server, useful for testing various timeout issue for application running behind proxy

delayed response http server, useful for testing various timeout issue for application running behind proxy

Jan 22, 2022

Generate types and service clients from protobuf definitions annotated with http rules.

protoc-gen-typescript-http Generates Typescript types and service clients from protobuf definitions annotated with http rules. The generated types fol

Nov 22, 2022

Network address types

netaddr What This is a package containing a new IP address type for Go. See its docs: https://pkg.go.dev/inet.af/netaddr Motivation See https://tailsc

Dec 28, 2022

DeepCopy a portable app that allows you to copy all forms of specified file types from your entire file system of the computer

DeepCopy a portable app that allows you to copy all forms of specified file types from your entire file system of the computer

Dec 20, 2021

rconn is a multiplatform program for creating generic reverse connections. Lets you consume services that are behind firewall or NAT without opening ports or port-forwarding.

rconn is a multiplatform program for creating generic reverse connections. Lets you consume services that are behind firewall or NAT without opening ports or port-forwarding.

rconn (r[everse] conn[ection]) is a multiplatform program for creating reverse connections. It lets you consume services that are behind NAT and/or fi

Jan 1, 2023
Collection of useful golang code snippets, mainly for learning purposes

Go-Things Collection of go code snippets, tools, etc. mainly for learning purpos

Dec 31, 2021
Forms814 - A website builder, useful for writing data collection webapps quickly.
Forms814 - A website builder, useful for writing data collection webapps quickly.

forms814 A website builder, useful for writing data collection webapps quickly. Project Design The method in use here is to mix it with complicated fo

Oct 25, 2022
An experimental package that rely on go generics to implement collection functions utilities

go-underscore go-underscore is a utility-belt library for Golang that provides s

Mar 20, 2022
Nov 9, 2022
A wrapper for exposing a shared endpoint for Google Cloud Functions in go. API styled after Node.JS firebase-functions package.

firebase-fx A wrapper for Google Cloud Functions that simplifies the deployment of serverless applications. Meant to expose a similar API to the Fireb

Nov 7, 2022
Lux - A web library collection based on net/http

Lux - A web library collection based on net/http

Jan 7, 2023
golang useful http client

gequest 简体中文 | English 一个轻量级的、语义化的、链式操作的 golang http 客户端封装 用法 要求: golang >= 1.14 安装 go get -u "github.com/smallcatx0/gequest" import ( request "g

Sep 18, 2021
GBPool-- a simple but useful golang free proxy pool

GBPool-- a simple but useful golang free proxy pool Intro(English) (中文) GBPool, golang baipiao proxy pool, a free & simple golang proxy pool module, g

May 30, 2022
Generate Typescript types from Golang source code

?? tygo Tygo is a tool for generating Typescript typings from Golang source files that just works. Other than reflection-based methods it preserves co

Dec 16, 2022
llb - It's a very simple but quick backend for proxy servers. Can be useful for fast redirection to predefined domain with zero memory allocation and fast response.

llb What the f--k it is? It's a very simple but quick backend for proxy servers. You can setup redirect to your main domain or just show HTTP/1.1 404

Sep 27, 2022