{"id":13411606,"url":"https://github.com/esimov/gogu","last_synced_at":"2026-01-12T02:59:47.463Z","repository":{"id":64300537,"uuid":"470997938","full_name":"esimov/gogu","owner":"esimov","description":"A comprehensive, reusable and efficient concurrent-safe generics utility functions and data structures library.","archived":false,"fork":false,"pushed_at":"2023-03-04T09:36:46.000Z","size":375,"stargazers_count":105,"open_issues_count":2,"forks_count":8,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-06-27T15:07:13.738Z","etag":null,"topics":["data-structures","datastructures","functional","functional-programming","generics","go","golang","programming","trie"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/esimov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"esimov"}},"created_at":"2022-03-17T13:04:48.000Z","updated_at":"2025-06-07T17:40:12.000Z","dependencies_parsed_at":"2024-01-30T04:06:04.304Z","dependency_job_id":"eda9f296-050f-477c-9db6-14892e6ea876","html_url":"https://github.com/esimov/gogu","commit_stats":null,"previous_names":["esimov/torx"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/esimov/gogu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esimov%2Fgogu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esimov%2Fgogu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esimov%2Fgogu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esimov%2Fgogu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/esimov","download_url":"https://codeload.github.com/esimov/gogu/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esimov%2Fgogu/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262279162,"owners_count":23286550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-structures","datastructures","functional","functional-programming","generics","go","golang","programming","trie"],"created_at":"2024-07-30T20:01:14.940Z","updated_at":"2026-01-12T02:59:47.455Z","avatar_url":"https://github.com/esimov.png","language":"Go","funding_links":["https://github.com/sponsors/esimov"],"categories":["Data Integration Frameworks","数据结构与算法","Data Structures and Algorithms"],"sub_categories":["Miscellaneous Data Structures and Algorithms","杂项数据结构和算法"],"readme":"# gogu (Go Generics Utility)\n![Coverage](https://img.shields.io/badge/Coverage-93.8%25-brightgreen)\n[![Go Report Card](https://goreportcard.com/badge/github.com/esimov/gogu)](https://goreportcard.com/report/github.com/esimov/gogu)\n[![CI](https://github.com/esimov/gogu/actions/workflows/ci.yml/badge.svg)](https://github.com/esimov/gogu/actions/workflows/ci.yml)\n[![Go Reference](https://img.shields.io/badge/pkg.go.dev-reference-007d9c?logo=go)](https://pkg.go.dev/github.com/esimov/gogu)\n[![release](https://img.shields.io/badge/Release-v1.0.3-blue.svg)](https://github.com/esimov/gogu/releases/tag/v1.0.3)\n[![license](https://img.shields.io/github/license/esimov/pigo)](./LICENSE)\n\n**Gogu** is a versatile, comprehensive, reusable and efficient concurrent-safe utility functions and data structures library taking advantage of the Go generics. It was inspired by other well known and established frameworks like [lodash](https://lodash.com/) or [Apache Commons](https://commons.apache.org/) and some concepts being more closer to the functional programming paradigms.\n\nIts main purpose is to facilitate the ease of working with common data structures like slices, maps and strings, through the implementation of many utility functions commonly used in the day-by-day jobs, but also integrating some of the most used data structure algorithms.\n\n## ✨ Features\n**In what's different this library from other Go libraries exploring Go generics?** \n- [x] It's concurrent-safe (with the exception of B-tree package)\n- [x] Implements a dozens of time related functions like: [`before`](\u003c#func-before\u003e), [`after`](\u003c#func-after\u003e), [`delay`](\u003c#func-delay\u003e), [`memoize`](\u003c#func-memoizert-v-memoize\u003e), [`debounce`](\u003c#func-newdebounce\u003e), [`once`](\u003c#func-once\u003e), [`retry`](\u003c#func-rtypet-retry\u003e)\n- [x] Rich utility functions to operate with strings\n- [x] Very wide range of supported functions to deal with slice and map operations\n- [x] Extensive test coverage\n- [x] Implements the most used data structures\n- [x] Thourough documentation accompanied with examples\n\n## 🚀 Run\n\n```bash\n$ go get github.com/esimov/gogu\n```\n\n## 🛠 Usage\n```go\npackage main\n\nimport \"github.com/esimov/gogu\"\n\nfunc main() {\n  // main program\n}\n```\n\n## 📖 Specifications\n- **Generic Data Structures**\n  - [`bst`](https://github.com/esimov/gogu/tree/master/bstree): Binary Search Tree data structure implementation, where each node has at most two child nodes and the key of its internal node is greater than all the keys in the respective node's left subtree and less than the ones in the right subtree\n  - [`btree`](https://github.com/esimov/gogu/tree/master/btree): B-tree data structure implementation which is a self-balancing tree data structure maintaining its values in sorted order\n  - [`cache`](https://github.com/esimov/gogu/tree/master/cache): a basic in-memory key-value storage system\n  - [`heap`](https://github.com/esimov/gogu/tree/master/heap): Binary Heap data structure implementation where each node of the subtree is greather or equal then the parent node\n  - [`list`](https://github.com/esimov/gogu/tree/master/list): implements a singly and doubly linked list data structure\n  - [`queue`](https://github.com/esimov/gogu/tree/master/queue): package queue implements a FIFO (First-In-First-Out) data structure in two forms: using as storage system a resizing array and a doubly linked list\n  - [`stack`](https://github.com/esimov/gogu/tree/master/stack): package stack implements a LIFO (Last-In-First-Out) data structure where the last element added to the stack is processed first\n  - [`trie`](https://github.com/esimov/gogu/tree/master/trie): package trie provides a thread safe implementation of the ternary search tree data structure. Tries are used for locating specific keys from within a set or for quick lookup searches within a text like auto-completion or spell checking.\n\n- **General utility functions**\n  - [Abs](\u003c#func-abs\u003e)\n  - [Clamp](\u003c#func-clamp\u003e)\n  - [Compare](\u003c#func-compare\u003e)\n  - [Equal](\u003c#func-equal\u003e)\n  - [InRange](\u003c#func-inrange\u003e)\n  - [Invert](\u003c#func-invert\u003e)\n  - [Less](\u003c#func-less\u003e)\n  - [Max](\u003c#func-max\u003e)\n  - [Min](\u003c#func-min\u003e)\n\n- **Strings utility functions**\n  - [CamelCase](\u003c#func-camelcase\u003e)\n  - [Capitalize](\u003c#func-capitalize\u003e)\n  - [KebabCase](\u003c#func-kebabcase\u003e)\n  - [N](\u003c#func-n\u003e)\n  - [Null](\u003c#func-null\u003e)\n  - [NumToString](\u003c#func-numtostring\u003e)\n  - [Pad](\u003c#func-pad\u003e)\n  - [PadLeft](\u003c#func-padleft\u003e)\n  - [PadRight](\u003c#func-padright\u003e)\n  - [ReverseStr](\u003c#func-reversestr\u003e)\n  - [SnakeCase](\u003c#func-snakecase\u003e)\n  - [SplitAtIndex](\u003c#func-splitatindex\u003e)\n  - [Substr](\u003c#func-substr\u003e)\n  - [ToLower](\u003c#func-tolower\u003e)\n  - [ToUpper](\u003c#func-toupper\u003e)\n  - [Unwrap](\u003c#func-unwrap\u003e)\n  - [Wrap](\u003c#func-wrap\u003e)\n  - [WrapAllRune](\u003c#func-wrapallrune\u003e)\n\n- **Slice utility functions**\n  - [Chunk](\u003c#func-chunk\u003e)\n  - [SumBy](#sumby)\n  - [Contains](\u003c#func-contains\u003e)\n  - [Difference](\u003c#func-difference\u003e)\n  - [DifferenceBy](\u003c#func-differenceby\u003e)\n  - [Drop](\u003c#func-drop\u003e)\n  - [DropWhile](\u003c#func-dropwhile\u003e)\n  - [DropRightWhile](\u003c#func-droprightwhile\u003e)\n  - [Duplicate](\u003c#func-duplicate\u003e)\n  - [DuplicateWithIndex](\u003c#func-duplicatewithindex\u003e)\n  - [Every](\u003c#func-every\u003e)\n  - [Filter](\u003c#func-filter\u003e)\n  - [FindAll](\u003c#func-findall\u003e)\n  - [FindIndex](\u003c#func-findindex\u003e)\n  - [FindLastIndex](\u003c#func-findlastindex\u003e)\n  - [FindMax](\u003c#func-findmax\u003e)\n  - [FindMaxBy](\u003c#func-findmaxby\u003e)\n  - [FindMaxByKey](\u003c#func-findmaxbykey\u003e)\n  - [FindMin](\u003c#func-findmin\u003e)\n  - [FindMinBy](\u003c#func-findminby\u003e)\n  - [FindMinByKey](\u003c#func-findminbykey\u003e)\n  - [Flatten](\u003c#func-flatten\u003e)\n  - [ForEach](\u003c#func-foreach\u003e)\n  - [ForEachRight](\u003c#func-foreachright\u003e)\n  - [GroupBy](\u003c#func-groupby\u003e)\n  - [IndexOf](\u003c#func-indexof\u003e)\n  - [Intersection](\u003c#func-intersection\u003e)\n  - [IntersectionBy](\u003c#func-intersectionby\u003e)\n  - [LastIndexOf](\u003c#func-lastindexof\u003e)\n  - [Mean](\u003c#func-mean\u003e)\n  - [Merge](\u003c#func-merge\u003e)\n  - [Nth](\u003c#func-nth\u003e)\n  - [Partition](\u003c#func-partition\u003e)\n  - [PartitionMap](\u003c#func-partitionmap\u003e)\n  - [Pluck](\u003c#func-pluck\u003e)\n  - [Range](\u003c#func-range\u003e)\n  - [RangeRight](\u003c#func-rangeright\u003e)\n  - [Reduce](\u003c#func-reduce\u003e)\n  - [Reject](\u003c#func-reject\u003e)\n  - [Reverse](\u003c#func-reverse\u003e)\n  - [Shuffle](\u003c#func-shuffle\u003e)\n  - [SliceToMap](\u003c#func-slicetomap\u003e)\n  - [Some](\u003c#func-some\u003e)\n  - [Sum](\u003c#func-sum\u003e)\n  - [SumBy](\u003c#func-sumby\u003e)\n  - [ToSlice](\u003c#func-toslice\u003e)\n  - [Union](\u003c#func-union\u003e)\n  - [Unique](\u003c#func-unique\u003e)\n  - [UniqueBy](\u003c#func-uniqueby\u003e)\n  - [Unzip](\u003c#func-unzip\u003e)\n  - [Without](\u003c#func-without\u003e)\n  - [Zip](\u003c#func-zip\u003e)\n\n- **Map utility functions**\n  - [Filter2DMapCollection](\u003c#func-filter2dmapcollection\u003e)\n  - [FilterMap](\u003c#func-filtermap\u003e)\n  - [FilterMapCollection](\u003c#func-filtermapcollection\u003e)\n  - [Find](\u003c#func-find\u003e)\n  - [FindByKey](\u003c#func-findbykey\u003e)\n  - [FindKey](\u003c#func-findkey\u003e)\n  - [Keys](\u003c#func-keys\u003e)\n  - [Map](\u003c#func-map\u003e)\n  - [MapCollection](\u003c#func-mapcollection\u003e)\n  - [MapContains](\u003c#func-mapcontains\u003e)\n  - [MapEvery) bool](\u003c#func-mapevery\u003e)\n  - [MapKeys](\u003c#func-mapkeys\u003e)\n  - [MapSome](\u003c#func-mapsome\u003e)\n  - [MapUnique](\u003c#func-mapunique\u003e)\n  - [MapValues](\u003c#func-mapvalues\u003e)\n  - [Omit](\u003c#func-omit\u003e)\n  - [OmitBy](\u003c#func-omitby\u003e)\n  - [Pick](\u003c#func-pick\u003e)\n  - [PickBy](\u003c#func-pickby\u003e)\n  - [Values](\u003c#func-values\u003e)\n\n- **Concurrency and time related utility functions**\n  - [After](\u003c#func-after\u003e)\n  - [Before](\u003c#func-before\u003e)\n  - [Delay](\u003c#func-delay\u003e)\n  - [Flip](\u003c#func-flip\u003e)\n  - [Memoize](\u003c#func-memoizert-v-memoize\u003e)\n  - [NewDebounce](\u003c#func-newdebounce\u003e)\n  - [Once](\u003c#func-once\u003e)\n  - [Retry](\u003c#func-rtypet-retry\u003e)\n  - [RetryWithDelay](\u003c#func-rtypet-retrywithdelay\u003e)\n\n## func Abs\n\n## func [Abs](\u003chttps://github.com/esimov/gogu/blob/master/math.go#L30\u003e)\n\n```go\nfunc Abs[T Number](x T) T\n```\n\nAbs returns the absolut value of x.\n\n## func [After](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L29\u003e)\n\n```go\nfunc After[V constraints.Signed](n *V, fn func())\n```\n\nAfter creates a function wrapper that does nothing at first. From the nth call onwards, it starts actually invoking the callback function. Useful for grouping responses, where you need to be sure that all the calls have finished just before proceeding to the actual job.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tsample := []int{1, 2, 3, 4, 5, 6}\n\tlength := len(sample) - 1\n\n\tinitVal := 0\n\tfn := func(val int) int {\n\t\treturn val + 1\n\t}\n\n\tForEach(sample, func(val int) {\n\t\tnow := time.Now()\n\t\tAfter(\u0026length, func() {\n\t\t\t\u003c-time.After(10 * time.Millisecond)\n\t\t\tinitVal = fn(initVal)\n\t\t\tafter := time.Since(now).Milliseconds()\n\t\t\tfmt.Println(after)\n\t\t})\n\t})\n\n}\n```\n\n#### Output\n\n```\n10\n```\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Before](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L39\u003e)\n\n```go\nfunc Before[S ~string, T any, V constraints.Signed](n *V, c *cache.Cache[S, T], fn func() T) T\n```\n\nBefore creates a function wrapper that memoizes its return value. From the nth call onwards, the memoized result of the last invocation is returned immediately instead of invoking function again. So the wrapper will invoke function at most n\\-1 times.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n  c := cache.New[string, int](cache.DefaultExpiration, cache.NoExpiration)\n\n\tvar n = 3\n\tsample := []int{1, 2, 3}\n\tForEach(sample, func(val int) {\n\t\tfn := func() int {\n\t\t\t\u003c-time.After(10 * time.Millisecond)\n\t\t\treturn n\n\t\t}\n\t\tres := Before(\u0026n, c, fn)\n\t\t// The trick to test this function is to decrease the n value after each iteration.\n\t\t// We can be sure that the callback function is not served from the cache if n \u003e 0.\n\t\t// In this case the cache item \"func\" should be empty.\n\t\tif n \u003e 0 {\n\t\t\tval, _ := c.Get(\"func\")\n\t\t\tfmt.Println(val)\n\t\t\tfmt.Println(res)\n\t\t}\n\t\tif n \u003c= 0 {\n\t\t\t// Here the callback function is served from the cache.\n\t\t\tval, _ := c.Get(\"func\")\n\t\t\tfmt.Println(val)\n\t\t\tfmt.Println(res)\n\t\t}\n\t})\n}\n```\n\n#### Output\n\n```\n\u003cnil\u003e\n2\n\u003cnil\u003e\n1\n\u0026{0 0}\n0\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [CamelCase](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L96\u003e)\n\n```go\nfunc CamelCase[T ~string](str T) T\n```\n\nCamelCase converts a string to camelCase \\(https://en.wikipedia.org/wiki/CamelCase\\).\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(CamelCase(\"Foo Bar\"))\n\tfmt.Println(CamelCase(\"--foo-Bar--\"))\n\tfmt.Println(CamelCase(\"__foo-_Bar__\"))\n\tfmt.Println(CamelCase(\"__FOO BAR__\"))\n\tfmt.Println(CamelCase(\" FOO BAR \"))\n\tfmt.Println(CamelCase(\"\u0026FOO\u0026baR \"))\n\tfmt.Println(CamelCase(\"\u0026\u0026foo\u0026\u0026bar__\"))\n}\n```\n\n#### Output\n\n```\nfooBar\nfooBar\nfooBar\nfooBar\nfooBar\nfooBar\nfooBar\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Capitalize](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L81\u003e)\n\n```go\nfunc Capitalize[T ~string](str T) T\n```\n\nCapitalize converts the first letter of the string to uppercase and the remaining letters to lowercase.\n\n## func [Chunk](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L405\u003e)\n\n```go\nfunc Chunk[T comparable](slice []T, size int) [][]T\n```\n\nChunk split the slice into groups of slices each having the length of size. In case the source slice cannot be distributed equally, the last slice will contain fewer elements.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(Chunk([]int{0, 1, 2, 3}, 2))\n\tfmt.Println(Chunk([]int{0, 1, 2, 3, 4}, 2))\n\tfmt.Println(Chunk([]int{0, 1}, 1))\n\n}\n```\n\n#### Output\n\n```\n[[0 1] [2 3]]\n[[0 1] [2 3] [4]]\n[[0] [1]]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Clamp](\u003chttps://github.com/esimov/gogu/blob/master/math.go#L38\u003e)\n\n```go\nfunc Clamp[T Number](num, min, max T) T\n```\n\nClamp returns a range\\-limited number between min and max.\n\n## func [Compare](\u003chttps://github.com/esimov/gogu/blob/master/generic.go#L11\u003e)\n\n```go\nfunc Compare[T comparable](a, b T, comp CompFn[T]) int\n```\n\nCompare compares two values using as comparator the callback function argument.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres1 := Compare(1, 2, func(a, b int) bool {\n\t\treturn a \u003c b\n\t})\n\tfmt.Println(res1)\n\n\tres2 := Compare(\"a\", \"b\", func(a, b string) bool {\n\t\treturn a \u003e b\n\t})\n\tfmt.Println(res2)\n\n}\n```\n\n#### Output\n\n```\n1\n-1\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Contains](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L172\u003e)\n\n```go\nfunc Contains[T comparable](slice []T, value T) bool\n```\n\nContains returns true if the value is present in the collection.\n\n## func [Delay](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L20\u003e)\n\n```go\nfunc Delay(delay time.Duration, fn func()) *time.Timer\n```\n\nDelay invokes the callback function with a predefined delay.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tch := make(chan struct{})\n\tnow := time.Now()\n\n\tvar value uint32\n\ttimer := Delay(20*time.Millisecond, func() {\n\t\tatomic.AddUint32(\u0026value, 1)\n\t\tch \u003c- struct{}{}\n\t})\n\tr1 := atomic.LoadUint32(\u0026value)\n\tfmt.Println(r1)\n\t\u003c-ch\n\tif timer.Stop() {\n\t\t\u003c-timer.C\n\t}\n\tr1 = atomic.LoadUint32(\u0026value)\n\tfmt.Println(r1)\n\tafter := time.Since(now).Milliseconds()\n\tfmt.Println(after)\n\n}\n```\n\n#### Output\n\n```\n0\n1\n20\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Difference](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L363\u003e)\n\n```go\nfunc Difference[T comparable](s1, s2 []T) []T\n```\n\nDifference is similar to Without, but returns the values from the first slice that are not present in the second slice.\n\n## func [DifferenceBy](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L384\u003e)\n\n```go\nfunc DifferenceBy[T comparable](s1, s2 []T, fn func(T) T) []T\n```\n\nDifferenceBy is like Difference, except that invokes a callback function on each element of the slice, applying the criteria by which the difference is computed.\n\n## func [Drop](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L425\u003e)\n\n```go\nfunc Drop[T any](slice []T, n int) []T\n```\n\nDrop creates a new slice with n elements dropped from the beginning. If n \\\u003c 0 the elements will be dropped from the back of the collection.\n\n## func [DropWhile](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L438\u003e)\n\n```go\nfunc DropWhile[T any](slice []T, fn func(T) bool) []T\n```\n\nDropWhile creates a new slice excluding the elements dropped from the beginning. Elements are dropped by applying the condition invoked in the callback function.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres := DropWhile([]string{\"a\", \"aa\", \"bbb\", \"ccc\"}, func(elem string) bool {\n\t\treturn len(elem) \u003e 2\n\t})\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\n[a aa]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [DropRightWhile](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L452\u003e)\n\n```go\nfunc DropRightWhile[T any](slice []T, fn func(T) bool) []T\n```\n\nDropRightWhile creates a new slice excluding the elements dropped from the end. Elements are dropped by applying the condition invoked in the callback function.\n\n## func [Duplicate](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L182\u003e)\n\n```go\nfunc Duplicate[T comparable](slice []T) []T\n```\n\nDuplicate returns the duplicated values of a collection.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []int{-1, -1, 0, 1, 2, 3, 2, 5, 1, 6}\n\tfmt.Println(Duplicate(input))\n}\n```\n\n#### Output\n\n```\n[-1 1 2]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [DuplicateWithIndex](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L206\u003e)\n\n```go\nfunc DuplicateWithIndex[T comparable](slice []T) map[T]int\n```\n\nDuplicateWithIndex puts the duplicated values of a collection into a map as a key value pair, where the key is the collection element and the value is its position.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []int{-1, -1, 0, 1, 2, 3, 2, 5, 1, 6}\n\tfmt.Println(DuplicateWithIndex(input))\n\n}\n```\n\n#### Output\n\n```\nmap[-1:0 1:3 2:4]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Equal](\u003chttps://github.com/esimov/gogu/blob/master/generic.go#L21\u003e)\n\n```go\nfunc Equal[T comparable](a, b T) bool\n```\n\nEqual checks if two values are equal.\n\n## func [Every](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L136\u003e)\n\n```go\nfunc Every[T any](slice []T, fn func(T) bool) bool\n```\n\nEvery returns true if all the elements of a slice satisfies the criteria of the callback function.\n\n## func [Filter](\u003chttps://github.com/esimov/gogu/blob/master/filter.go#L4\u003e)\n\n```go\nfunc Filter[T any](slice []T, fn func(T) bool) []T\n```\n\nFilter returns all the elements from the collection which satisfies the conditional logic of the callback function.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []int{1, 2, 3, 4, 5, 10, 20, 30, 40, 50}\n\tres := Filter(input, func(val int) bool {\n\t\treturn val \u003e= 10\n\t})\n\tfmt.Println(res)\n}\n```\n\n#### Output\n\n```\n[10 20 30 40 50]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Filter2DMapCollection](\u003chttps://github.com/esimov/gogu/blob/master/filter.go#L63\u003e)\n\n```go\nfunc Filter2DMapCollection[K comparable, V any](collection []map[K]map[K]V, fn func(map[K]V) bool) []map[K]map[K]V\n```\n\nFilter2DMapCollection filter out a two\\-dimensional collection of map items by applying the conditional logic of the callback function.\n\n## func [FilterMap](\u003chttps://github.com/esimov/gogu/blob/master/filter.go#L33\u003e)\n\n```go\nfunc FilterMap[K comparable, V any](m map[K]V, fn func(V) bool) map[K]V\n```\n\nFilterMap iterates over the elements of a collection and returns a new collection representing all the items which satisfies the criteria formulated in the callback function.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := map[int]string{1: \"John\", 2: \"Doe\", 3: \"Fred\"}\n\tres := FilterMap(input, func(v string) bool {\n\t\treturn v == \"John\"\n\t})\n\tfmt.Println(res)\n}\n```\n\n#### Output\n\n```\nmap[1:John]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [FilterMapCollection](\u003chttps://github.com/esimov/gogu/blob/master/filter.go#L47\u003e)\n\n```go\nfunc FilterMapCollection[K comparable, V any](collection []map[K]V, fn func(V) bool) []map[K]V\n```\n\nFilterMapCollection filter out a one dimensional collection of map items by applying the conditional logic of the callback function.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []map[string]int{\n\t\t{\"bernie\": 22},\n\t\t{\"robert\": 30},\n\t}\n\tres := FilterMapCollection(input, func(val int) bool {\n\t\treturn val \u003e 22\n\t})\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\n[map[robert:30]]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Find](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L128\u003e)\n\n```go\nfunc Find[K constraints.Ordered, V any](m map[K]V, fn func(V) bool) map[K]V\n```\n\nFind iterates over the elements of a map and returns the first item for which the callback function returns true.\n\n## func [FindAll](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L33\u003e)\n\n```go\nfunc FindAll[T any](s []T, fn func(T) bool) map[int]T\n```\n\nFindAll is like FindIndex, but returns into a map all the values which satisfies the conditional logic of the callback function. The map key represents the position of the found value and the value is the item itself.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []int{1, 2, 3, 4, 2, -2, -1, 2}\n\titems := FindAll(input, func(v int) bool {\n\t\treturn v == 2\n\t})\n\tfmt.Println(items)\n\n}\n```\n\n#### Output\n\n```\nmap[1:2 4:2 7:2]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [FindByKey](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L167\u003e)\n\n```go\nfunc FindByKey[K comparable, V any](m map[K]V, fn func(K) bool) map[K]V\n```\n\nFindByKey is like Find, but returns the first item for which the callback function returns true.\n\n## func [FindIndex](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L11\u003e)\n\n```go\nfunc FindIndex[T any](s []T, fn func(T) bool) int\n```\n\nFindIndex returns the index of the first found element.\n\n## func [FindKey](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L155\u003e)\n\n```go\nfunc FindKey[K comparable, V any](m map[K]V, fn func(V) bool) K\n```\n\nFindKey is like Find, but returns the first item key position for which the callback function returns true.\n\n## func [FindLastIndex](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L21\u003e)\n\n```go\nfunc FindLastIndex[T any](s []T, fn func(T) bool) int\n```\n\nFindLastIndex is like FindIndex, only that returns the index of last found element.\n\n## func [FindMax](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L103\u003e)\n\n```go\nfunc FindMax[T constraints.Ordered](s []T) T\n```\n\nFindMax finds the maximum value of a slice.\n\n## func [FindMaxBy](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L120\u003e)\n\n```go\nfunc FindMaxBy[T constraints.Ordered](s []T, fn func(val T) T) T\n```\n\nFindMaxBy is like FindMax except that it accept a callback function and the conditional logic is applied over the resulted value. If there are more than one identical values resulted from the callback function the first one is returned.\n\n## func [FindMaxByKey](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L135\u003e)\n\n```go\nfunc FindMaxByKey[K comparable, T constraints.Ordered](mapSlice []map[K]T, key K) (T, error)\n```\n\nFindMaxByKey finds the maximum value from a map by using some existing key as a parameter.\n\n## func [FindMin](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L46\u003e)\n\n```go\nfunc FindMin[T constraints.Ordered](s []T) T\n```\n\nFindMin finds the minimum value of a slice.\n\n## func [FindMinBy](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L63\u003e)\n\n```go\nfunc FindMinBy[T constraints.Ordered](s []T, fn func(val T) T) T\n```\n\nFindMinBy is like FindMin except that it accept a callback function and the conditional logic is applied over the resulted value. If there are more than one identical values resulted from the callback function the first one is used.\n\n## func [FindMinByKey](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L78\u003e)\n\n```go\nfunc FindMinByKey[K comparable, T constraints.Ordered](mapSlice []map[K]T, key K) (T, error)\n```\n\nFindMinByKey finds the minimum value from a map by using some existing key as a parameter.\n\n## func [Flatten](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L248\u003e)\n\n```go\nfunc Flatten[T any](slice any) ([]T, error)\n```\n\nFlatten flattens the slice all the way down to the deepest nesting level.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []any{[]int{1, 2, 3}, []any{[]int{4}, 5}}\n\tresult, _ := Flatten[int](input)\n\tfmt.Println(result)\n\n}\n```\n\n#### Output\n\n```\n[1 2 3 4 5]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Flip](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L13\u003e)\n\n```go\nfunc Flip[T any](fn func(args ...T) []T) func(args ...T) []T\n```\n\nFlip creates a function that invokes fn with arguments reversed.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tflipped := Flip(func(args ...int) []int {\n\t\treturn ToSlice(args...)\n\t})\n\tfmt.Println(flipped(1, 2, 3))\n\n}\n```\n\n#### Output\n\n```\n[3 2 1]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [ForEach](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L69\u003e)\n\n```go\nfunc ForEach[T any](slice []T, fn func(T))\n```\n\nForEach iterates over the elements of a collection and invokes the callback fn function on each element.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []int{1, 2, 3, 4}\n\toutput := []int{}\n\n\tForEach(input, func(val int) {\n\t\tval = val * 2\n\t\toutput = append(output, val)\n\t})\n\tfmt.Println(output)\n\n}\n```\n\n#### Output\n\n```\n[2 4 6 8]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [ForEachRight](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L76\u003e)\n\n```go\nfunc ForEachRight[T any](slice []T, fn func(T))\n```\n\nForEachRight is the same as ForEach, but starts the iteration from the last element.\n\n## func [GroupBy](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L481\u003e)\n\n```go\nfunc GroupBy[T1, T2 comparable](slice []T1, fn func(T1) T2) map[T2][]T1\n```\n\nGroupBy splits a collection into a key\\-value set, grouped by the result of running each value through the callback function fn. The return value is a map where the key is the conditional logic of the callback function and the values are the callback function returned values.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []float64{1.3, 1.5, 2.1, 2.9}\n\tres := GroupBy(input, func(val float64) float64 {\n\t\treturn math.Floor(val)\n\t})\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\nmap[1:[1.3 1.5] 2:[2.1 2.9]]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [InRange](\u003chttps://github.com/esimov/gogu/blob/master/math.go#L48\u003e)\n\n```go\nfunc InRange[T Number](num, lo, up T) bool\n```\n\nInRange checks if a number is inside a range.\n\n## func [IndexOf](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L38\u003e)\n\n```go\nfunc IndexOf[T comparable](s []T, val T) int\n```\n\nIndexOf returns the index of the firs occurrence of a value in the slice, or \\-1 if value is not present in the slice.\n\n## func [Intersection](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L286\u003e)\n\n```go\nfunc Intersection[T comparable](params ...[]T) []T\n```\n\nIntersection computes the list of values that are the intersection of all the slices. Each value in the result should be present in each of the provided slices.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres1 := Intersection([]int{1, 2, 4}, []int{0, 2, 1}, []int{2, 1, -2})\n\tfmt.Println(res1)\n\n\tres2 := Intersection([]string{\"a\", \"b\"}, []string{\"a\", \"a\", \"a\"}, []string{\"b\", \"a\", \"e\"})\n\tfmt.Println(res2)\n\n}\n```\n\n#### Output\n\n```\n[1 2]\n[a]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [IntersectionBy](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L310\u003e)\n\n```go\nfunc IntersectionBy[T comparable](fn func(T) T, params ...[]T) []T\n```\n\nIntersectionBy is like Intersection, except that it accepts and callback function which is invoked on each element of the collection.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tresult1 := IntersectionBy(func(v float64) float64 {\n\t\treturn math.Floor(v)\n\t}, []float64{2.1, 1.2}, []float64{2.3, 3.4}, []float64{1.0, 2.3})\n\tfmt.Println(result1)\n\n\tresult2 := IntersectionBy(func(v int) int {\n\t\treturn v % 2\n\t}, []int{1, 2}, []int{2, 1})\n\tfmt.Println(result2)\n\n}\n```\n\n#### Output\n\n```\n[2.1]\n[1 2]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Invert](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L180\u003e)\n\n```go\nfunc Invert[K, V comparable](m map[K]V) map[V]K\n```\n\nInvert returns a copy of the map where the keys become the values and the values the keys. For this to work, all of your map's values should be unique.\n\n## func [KebabCase](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L132\u003e)\n\n```go\nfunc KebabCase[T ~string](str T) T\n```\n\nKebabCase converts a string to kebab\\-case \\(https://en.wikipedia.org/wiki/Letter_case#Kebab_case\\).\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(KebabCase(\"fooBarBaz\"))\n\tfmt.Println(KebabCase(\"Foo BarBaz\"))\n\tfmt.Println(KebabCase(\"Foo_Bar_Baz\"))\n\n}\n```\n\n#### Output\n\n```\nfoo-bar-baz\nfoo-bar-baz\nfoo-bar-baz\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func Keys\n\n```go\nfunc Keys[K comparable, V any](m map[K]V) []K\n```\n\nKeys retrieve all the existing keys of a map.\n\n## func [LastIndexOf](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L49\u003e)\n\n```go\nfunc LastIndexOf[T comparable](s []T, val T) int\n```\n\nLastIndexOf returns the index of the last occurrence of a value.\n\n## func [Less](\u003chttps://github.com/esimov/gogu/blob/master/generic.go#L26\u003e)\n\n```go\nfunc Less[T constraints.Ordered](a, b T) bool\n```\n\nLess checks if the first value is less than the second.\n\n## func [Map](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L59\u003e)\n\n```go\nfunc Map[T1, T2 any](slice []T1, fn func(T1) T2) []T2\n```\n\nMap produces a new slice of values by mapping each value in the list through a transformation function.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres := Map([]int{1, 2, 3}, func(val int) int {\n\t\treturn val * 2\n\t})\n\tfmt.Println()\n\n}\n```\n\n#### Output\n\n```\n[2 4 6]\n```\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [MapCollection](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L116\u003e)\n\n```go\nfunc MapCollection[K comparable, V any](m map[K]V, fn func(V) V) []V\n```\n\nMapCollection is like the Map method, but applied to maps. It runs each element of the map over an iteratee function and saves the resulted values into a new map.\n\n## func [MapContains](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L89\u003e)\n\n```go\nfunc MapContains[K, V comparable](m map[K]V, value V) bool\n```\n\nMapContains returns true if the value is present in the list otherwise false.\n\n## func [MapEvery](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L67\u003e)\n\n```go\nfunc MapEvery[K comparable, V any](m map[K]V, fn func(V) bool) bool\n```\n\nMapEvery returns true if all the elements of a map satisfies the criteria of the callback function.\n\n## func [MapKeys](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L56\u003e)\n\n```go\nfunc MapKeys[K comparable, V any, R comparable](m map[K]V, fn func(K, V) R) map[R]V\n```\n\nMapKeys is the opposite of MapValues. It creates a new map with the same number of elements as the original one, but this time the callback function \\(fn\\) is invoked over the map keys.\n\n## func [MapSome](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L78\u003e)\n\n```go\nfunc MapSome[K comparable, V any](m map[K]V, fn func(V) bool) bool\n```\n\nMapSome returns true if some elements of a map satisfies the criteria of the callback function.\n\n## func [MapUnique](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L99\u003e)\n\n```go\nfunc MapUnique[K, V comparable](m map[K]V) map[K]V\n```\n\nMapUnique removes the duplicate values from a map.\n\n## func [MapValues](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L44\u003e)\n\n```go\nfunc MapValues[K comparable, V, R any](m map[K]V, fn func(V) R) map[K]R\n```\n\nMapValues creates a new map with the same number of elements as the original one, but running each map value through a callback function \\(fn\\).\n\n## func [Max](\u003chttps://github.com/esimov/gogu/blob/master/math.go#L18\u003e)\n\n```go\nfunc Max[T constraints.Ordered](values ...T) T\n```\n\nMax returns the biggest value from the provided parameters.\n\n## func [Mean](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L28\u003e)\n\n```go\nfunc Mean[T Number](slice []T) T\n```\n\nMean computes the mean value of the slice elements.\n\n## func [Merge](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L236\u003e)\n\n```go\nfunc Merge[T any](s []T, params ...[]T) []T\n```\n\nMerge merges the first slice with the other slices defined as variadic parameter.\n\n## func [Min](\u003chttps://github.com/esimov/gogu/blob/master/math.go#L6\u003e)\n\n```go\nfunc Min[T constraints.Ordered](values ...T) T\n```\n\nMin returns the lowest value from the provided parameters.\n\n## func [N](\u003chttps://github.com/esimov/gogu/blob/master/range.go#L79\u003e)\n\n```go\nfunc N[T Number](s string) (T, error)\n```\n\nN converts a string to a generic number.\n\n## func [NewDebounce](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L125\u003e)\n\n```go\nfunc NewDebounce(wait time.Duration) (func(f func()), func())\n```\n\nNewDebounce creates a new debounced version of the invoked function which postpone the execution with a time delay passed in as a function argument. It returns a callback function which will be invoked after the predefined delay and also a cancel method which should be invoked to cancel a scheduled debounce.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tvar (\n\t\tcounter1 uint64\n\t\tcounter2 uint64\n\t)\n\n\tf1 := func() {\n\t\tatomic.AddUint64(\u0026counter1, 1)\n\t}\n\n\tf2 := func() {\n\t\tatomic.AddUint64(\u0026counter2, 1)\n\t}\n\n\tdebounce, cancel := NewDebounce(10 * time.Millisecond)\n\tfor i := 0; i \u003c 2; i++ {\n\t\tfor j := 0; j \u003c 100; j++ {\n\t\t\tdebounce(f1)\n\t\t}\n\t\t\u003c-time.After(20 * time.Millisecond)\n\t}\n\tcancel()\n\n\tdebounce, cancel = NewDebounce(10 * time.Millisecond)\n\tfor i := 0; i \u003c 5; i++ {\n\t\tfor j := 0; j \u003c 50; j++ {\n\t\t\tdebounce(f2)\n\t\t}\n\t\tfor j := 0; j \u003c 50; j++ {\n\t\t\tdebounce(f2)\n\t\t}\n\t\t\u003c-time.After(20 * time.Millisecond)\n\t}\n\tcancel()\n\n\tc1 := atomic.LoadUint64(\u0026counter1)\n\tc2 := atomic.LoadUint64(\u0026counter2)\n\tfmt.Println(c1)\n\tfmt.Println(c2)\n\n}\n```\n\n#### Output\n\n```\n2\n5\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Nth](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L162\u003e)\n\n```go\nfunc Nth[T any](slice []T, nth int) (T, error)\n```\n\nNth returns the nth element of the collection. In case of negative value the nth element is returned from the end of the collection. In case nth is out of bounds an error is returned.\n\n## func [Null](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L10\u003e)\n\n```go\nfunc Null[T any]() T\n```\n\n## func [NumToString](\u003chttps://github.com/esimov/gogu/blob/master/range.go#L108\u003e)\n\n```go\nfunc NumToString[T Number](n T) string\n```\n\nNumToString converts a number to a string. In case of a number of type float \\(float32|float64\\) this will be rounded to 2 decimal places.\n\n## func [Omit](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L237\u003e)\n\n```go\nfunc Omit[K comparable, V any](collection map[K]V, keys ...K) map[K]V\n```\n\nOmit is the opposite of Pick, it extracts all the map elements which keys are not omitted.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres := Omit(map[string]any{\"name\": \"moe\", \"age\": 40, \"active\": false}, \"name\", \"age\")\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\nmap[active:false]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [OmitBy](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L248\u003e)\n\n```go\nfunc OmitBy[K comparable, V any](collection map[K]V, fn func(key K, val V) bool) map[K]V\n```\n\nOmitBy is the opposite of PickBy, it removes all the map elements for which the callback function returns true.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres := OmitBy(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3}, func(key string, val int) bool {\n\t\treturn val%2 == 1\n\t})\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\nmap[b:2]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Once](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L56\u003e)\n\n```go\nfunc Once[S ~string, T comparable, V constraints.Signed](c *cache.Cache[S, T], fn func() T) T\n```\n\nOnce is like Before, but it's invoked only once. Repeated calls to the modified function will have no effect and the function invocation is returned from the cache.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tc := cache.New[string, int](cache.DefaultExpiration, cache.NoExpiration)\n\n\tForEach([]int{1, 2, 3, 4, 5}, func(val int) {\n\t\tfn := func(val int) func() int {\n\t\t\t\u003c-time.After(10 * time.Millisecond)\n\t\t\treturn func() int {\n\t\t\t\treturn val\n\t\t\t}\n\t\t}\n\t\tres := Once[string, int, int](c, fn(val))\n\n        // We can test the implementation correctness by invoking the `Once` function multiple times.\n\t    // When it's invoked for the first time the result should be served from the callback function.\n\t    // From the second invocation onward the results are served from the cache.\n\t    // In our example the results of each invokation should be always equal with 1.\n\t\tfmt.Println(res)\n\t})\n\tc.Flush()\n}\n```\n\n#### Output\n\n```\n1\n1\n1\n1\n1\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Pad](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L236\u003e)\n\n```go\nfunc Pad[T ~string](str T, size int, token string) T\n```\n\nPad pads string on the left and right sides if it's shorter than length. Padding characters are truncated if they can't be evenly divided by length.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(Pad(\"abc\", 2, \".\"))\n\tfmt.Println(Pad(\"abc\", 3, \".\"))\n\tfmt.Println(Pad(\"abc\", 4, \".\"))\n\tfmt.Println(Pad(\"abc\", 5, \".\"))\n}\n```\n\n#### Output\n\n```\nabc\nabc\nabc.\n.abc.\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [PadLeft](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L194\u003e)\n\n```go\nfunc PadLeft[T ~string](str T, size int, token string) T\n```\n\nPadLeft pads string on the left side if it's shorter than length. Padding characters are truncated if they exceed length.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(PadLeft(\"abc\", 8, \"...\"))\n\tfmt.Println(PadLeft(\"abc\", 4, \"_\"))\n\tfmt.Println(PadLeft(\"abc\", 6, \"_-\"))\n\n}\n```\n\n#### Output\n\n```\n.....abc\n_abc\n_-_abc\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [PadRight](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L215\u003e)\n\n```go\nfunc PadRight[T ~string](str T, size int, token string) T\n```\n\nPadRight pads string on the right side if it's shorter than length. Padding characters are truncated if they exceed length.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(PadRight(\"abc\", 8, \"...\"))\n\tfmt.Println(PadRight(\"abc\", 6, \"........\"))\n}\n```\n\n#### Output\n\n```\nabc.....\nabc...\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Partition](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L157\u003e)\n\n```go\nfunc Partition[T comparable](slice []T, fn func(T) bool) [2][]T\n```\n\nPartition splits the collection elements into two, the ones which satisfies the condition expressed in the callback function (`fn`) and those which does not satisfy the condition.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\tres1 := Partition(input, func(val int) bool {\n\t\treturn val \u003e= 5\n\t})\n\tfmt.Println(res1)\n\n\tres2 := Partition(input, func(val int) bool {\n\t\treturn val \u003c 5\n\t})\n\tfmt.Println(res2)\n\n}\n```\n\n#### Output\n\n```\n[[5 6 7 8 9] [0 1 2 3 4]]\n[[0 1 2 3 4] [5 6 7 8 9]]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [PartitionMap](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L260\u003e)\n\n```go\nfunc PartitionMap[K comparable, V any](mapSlice []map[K]V, fn func(map[K]V) bool) [2][]map[K]V\n```\n\nPartitionMap split the collection into two arrays, the one whose elements satisfy the condition expressed in the callback function (`fn`) and one whose elements don't satisfy the condition.\n\n## func [Pick](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L208\u003e)\n\n```go\nfunc Pick[K comparable, V any](collection map[K]V, keys ...K) (map[K]V, error)\n```\n\nPick extracts the elements from the map which have the key defined in the allowed keys.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres, _ := Pick(map[string]any{\"name\": \"moe\", \"age\": 20, \"active\": true}, \"name\", \"age\")\n\tfmt.Println(res)\n}\n```\n\n#### Output\n\n```\nmap[age:20 name:moe]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [PickBy](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L224\u003e)\n\n```go\nfunc PickBy[K comparable, V any](collection map[K]V, fn func(key K, val V) bool) map[K]V\n```\n\nPickBy extracts all the map elements for which the callback function returns truthy.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres := PickBy(map[string]int{\"aa\": 1, \"b\": 2, \"c\": 3}, func(key string, val int) bool {\n\t\treturn len(key) == 1\n\t})\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\nmap[b:2 c:3]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Pluck](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L192\u003e)\n\n```go\nfunc Pluck[K comparable, V any](mapSlice []map[K]V, key K) []V\n```\n\nPluck extracts all the values of a map by the key definition.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []map[string]string{\n\t\t{\"name\": \"moe\", \"email\": \"moe@example.com\"},\n\t\t{\"name\": \"larry\", \"email\": \"larry@example.com\"},\n\t\t{\"name\": \"curly\", \"email\": \"curly@example.com\"},\n\t\t{\"name\": \"moly\", \"email\": \"moly@example.com\"},\n\t}\n\tres := Pluck(input, \"name\")\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\n[moe larry curly moly]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Range](\u003chttps://github.com/esimov/gogu/blob/master/range.go#L21\u003e)\n\n```go\nfunc Range[T Number](args ...T) ([]T, error)\n```\n\nRange creates a slice of integers progressing from start up to, but not including end. This method can accept 1, 2 or 3 arguments. Depending on the number of provided parameters, \\`start\\`, \\`step\\` and \\`end\\` has the following meaning:\n\n\\[start=0\\]: The start of the range. If omitted it defaults to 0.\n\n\\[step=1\\]: The value to increment or decrement by.\n\nend: The end of the range.\n\nIn case you'd like negative values, use a negative step.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tr1, _ := Range(5)\n\tr2, _ := Range(1, 5)\n\tr3, _ := Range(0, 2, 10)\n\tr4, _ := Range(-4)\n\tr5, _ := Range(-1, -4)\n\tr6, _ := Range(0, -1, -4)\n\tr7, _ := Range[float64](0, 0.12, 0.9)\n\n\tfmt.Println(r1)\n\tfmt.Println(r2)\n\tfmt.Println(r3)\n\tfmt.Println(r4)\n\tfmt.Println(r5)\n\tfmt.Println(r6)\n\tfmt.Println(r7)\n\n}\n```\n\n#### Output\n\n```\n[0 1 2 3 4]\n[1 2 3 4]\n[0 2 4 6 8]\n[0 -1 -2 -3]\n[-1 -2 -3]\n[0 -1 -2 -3]\n[0 0.12 0.24 0.36 0.48 0.6 0.72 0.84]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [RangeRight](\u003chttps://github.com/esimov/gogu/blob/master/range.go#L70\u003e)\n\n```go\nfunc RangeRight[T Number](params ...T) ([]T, error)\n```\n\nRangeRight is like Range, only that it populates the slice in descending order.\n\n## func [Reduce](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L84\u003e)\n\n```go\nfunc Reduce[T1, T2 any](slice []T1, fn func(T1, T2) T2, initVal T2) T2\n```\n\nReduce reduces the collection to a value which is the accumulated result of running each element in the collection through the callback function yielding a single value.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput1 := []int{1, 2, 3, 4}\n\tres1 := Reduce(input1, func(a, b int) int {\n\t\treturn a + b\n\t}, 0)\n\tfmt.Println(res1)\n\n\tinput2 := []string{\"a\", \"b\", \"c\", \"d\"}\n\tres2 := Reduce(input2, func(a, b string) string {\n\t\treturn b + a\n\t}, \"\")\n\tfmt.Println(res2)\n\n}\n```\n\n#### Output\n\n```\n10\nabcd\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Reject](\u003chttps://github.com/esimov/gogu/blob/master/filter.go#L18\u003e)\n\n```go\nfunc Reject[T any](slice []T, fn func(val T) bool) []T\n```\n\nReject is the opposite of Filter. It returns the values from the collection without the elements for which the callback function returns true.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []int{1, 2, 3, 4, 5, 6, 10, 20, 30, 40, 50}\n\tres = Reject(input, func(val int) bool {\n\t\treturn val \u003e= 10\n\t})\n\tfmt.Println(res)\n}\n```\n\n#### Output\n\n```\n[1 2 3 4 5 6]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Reverse](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L96\u003e)\n\n```go\nfunc Reverse[T any](sl []T) []T\n```\n\nReverse reverses the order of elements, so that the first element becomes the last, the second element becomes the second to last, and so on.\n\n## func [ReverseStr](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L322\u003e)\n\n```go\nfunc ReverseStr[T ~string](str T) T\n```\n\nReverseStr returns a new string with the characters in reverse order.\n\n## func [Shuffle](\u003chttps://github.com/esimov/gogu/blob/master/shuffle.go#L8\u003e)\n\n```go\nfunc Shuffle[T any](src []T) []T\n```\n\nShuffle implements the Fisher\\-Yates shuffle algorithm applied to a slice.\n\n## func [SliceToMap](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L281\u003e)\n\n```go\nfunc SliceToMap[K comparable, T any](s1 []K, s2 []T) map[K]T\n```\n\nSliceToMap converts a slice to a map. It panics in case the parameter slices length are not identical. The map keys will be the items from the first slice and the values the items from the second slice.\n\n## func [SnakeCase](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L127\u003e)\n\n```go\nfunc SnakeCase[T ~string](str T) T\n```\n\nSnakeCase converts a string to snake\\_case \\(https://en.wikipedia.org/wiki/Snake_case\\).\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(SnakeCase(\"fooBarBaz\"))\n\tfmt.Println(SnakeCase(\"Foo BarBaz\"))\n\tfmt.Println(SnakeCase(\"Foo_Bar_Baz\"))\n\n}\n```\n\n#### Output\n\n```\nfoo_bar_baz\nfoo_bar_baz\nfoo_bar_baz\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Some](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L146\u003e)\n\n```go\nfunc Some[T any](slice []T, fn func(T) bool) bool\n```\n\nSome returns true if some elements of a slice satisfies the criteria of the callback function.\n\n## func [SplitAtIndex](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L265\u003e)\n\n```go\nfunc SplitAtIndex[T ~string](str T, index int) []T\n```\n\nSplitAtIndex split the string at the specified index and returns a slice with the resulted two substrings.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(SplitAtIndex(\"abcdef\", -1))\n\tfmt.Println(SplitAtIndex(\"abcdef\", 0))\n\tfmt.Println(SplitAtIndex(\"abcdef\", 1))\n\tfmt.Println(SplitAtIndex(\"abcdef\", 2))\n\tfmt.Println(SplitAtIndex(\"abcdef\", 5))\n\tfmt.Println(SplitAtIndex(\"abcdef\", 6))\n\n}\n```\n\n#### Output\n\n```\n[ abcdef]\n[a bcdef]\n[ab cdef]\n[abc def]\n[abcdef ]\n[abcdef ]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Substr](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L27\u003e)\n\n```go\nfunc Substr[T ~string](str T, offset, length int) T\n```\n\nSubstr returns the portion of string specified by the offset and length.\n\nIf offset is non\\-negative, the returned string will start at the offset'th position in string, counting from zero.\n\nIf offset is negative, the returned string will start at the offset'th character from the end of string.\n\nIf string is less than offset characters long, an empty string will be returned.\n\nIf length is negative, then that many characters will be omitted from the end of string starting from the offset position.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tstr1 := Substr(\"abcdef\", 0, 0)\n\tstr2 := Substr(\"abcdef\", -1, 0)\n\tstr3 := Substr(\"abcdef\", 7, 7)\n\tstr4 := Substr(\"abcdef\", 0, 20)\n\tstr5 := Substr(\"abcdef\", 5, 10)\n\tstr6 := Substr(\"abcdef\", 0, -1)\n\tstr7 := Substr(\"abcdef\", 2, -1)\n\tstr8 := Substr(\"abcdef\", 4, -4)\n\tstr9 := Substr(\"abcdef\", -3, -1)\n\tstr10 := Substr(\"abcdef\", 1, 3)\n\n\tfmt.Println(str1)\n\tfmt.Println(str2)\n\tfmt.Println(str3)\n\tfmt.Println(str4)\n\tfmt.Println(str5)\n\tfmt.Println(str6)\n\tfmt.Println(str7)\n\tfmt.Println(str8)\n\tfmt.Println(str9)\n\tfmt.Println(str10)\n\n}\n```\n\n#### Output\n\n```\nabcdef\nf\nabcde\ncde\n\nde\nbcd\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Sum](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L9\u003e)\n\n```go\nfunc Sum[T Number](slice []T) T\n```\n\nSum returns the sum of the slice items. These have to satisfy the type constraints declared as Number.\n\n## func [SumBy](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L19\u003e)\n\n```go\nfunc SumBy[T1 any, T2 Number](slice []T1, fn func(T1) T2) T2\n```\n\nSumBy is like Sum except it accept a callback function which is invoked for each element in the slice to generate the value to be summed.\n\n## func [ToLower](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L58\u003e)\n\n```go\nfunc ToLower[T ~string](str T) T\n```\n\nToLower converts a string to Lowercase.\n\n## func [ToSlice](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L544\u003e)\n\n```go\nfunc ToSlice[T any](args ...T) []T\n```\n\nToSlice returns the function arguments as a slice.\n\n## func [ToUpper](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L69\u003e)\n\n```go\nfunc ToUpper[T ~string](str T) T\n```\n\nToUpper converts a string to Uppercase.\n\n## func Union\n\n```go\nfunc Union[T comparable](slice any) ([]T, error)\n```\n\nUnion computes the union of the passed\\\\\\-in slice and returns an ordered list of unique items that are present in one or more of the slices.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tinput := []any{[]any{1, 2, []any{3, []int{4, 5, 6}}}, 7, []int{1, 2}, 3, []int{4, 7}, 8, 9, 9}\n\tres, _ := Union[int](input)\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\n[1 2 3 4 5 6 7 8 9]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Unique](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L105\u003e)\n\n```go\nfunc Unique[T comparable](slice []T) []T\n```\n\nUnique returns the collection unique values.\n\n## func [UniqueBy](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L121\u003e)\n\n```go\nfunc UniqueBy[T comparable](slice []T, fn func(T) T) []T\n```\n\nUniqueBy is like Unique except that it accept a callback function which is invoked on each element of the slice applying the criteria by which the uniqueness is computed.\n\n## func [Unwrap](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L297\u003e)\n\n```go\nfunc Unwrap[T ~string](str T, token string) T\n```\n\nUnwrap a string with the specified token.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(Unwrap(\"'abc'\", \"'\"))\n\tfmt.Println(Unwrap(\"*abc*\", \"*\"))\n\tfmt.Println(Unwrap(\"*a*bc*\", \"*\"))\n\tfmt.Println(Unwrap(\"''abc''\", \"''\"))\n\tfmt.Println(Unwrap(\"\\\"abc\\\"\", \"\\\"\"))\n\n}\n```\n\n#### Output\n\n```\nabc\nabc\na*bc\nabc\nabc\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Unzip](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L516\u003e)\n\n```go\nfunc Unzip[T any](slices ...[]T) [][]T\n```\n\nUnzip is the opposite of Zip: given a slice of slices it returns a series of new slices, the first of which contains all the first elements in the input slices, the second of which contains all the second elements, and so on.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres := Unzip([]any{\"one\", 1}, []any{\"two\", 2})\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\n[[one two] [1 2]]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Values](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L30\u003e)\n\n```go\nfunc Values[K comparable, V any](m map[K]V) []V\n```\n\nValues retrieve all the existing values of a map.\n\n## func [Without](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L342\u003e)\n\n```go\nfunc Without[T1 comparable, T2 any](slice []T1, values ...T1) []T1\n```\n\nWithout returns a copy of the slice with all the values defined in the variadic parameter removed.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(Without[int, int]([]int{2, 1, 2, 3}, 1, 2))\n\tfmt.Println(Without[int, int]([]int{1, 2, 3, 4}, 3, 4))\n\tfmt.Println(Without[int, int]([]int{0, 1, 2, 3, 4, 5}, 0, 3, 4, 5))\n\tfmt.Println(Without[float64, float64]([]float64{1.0, 2.2, 3.0, 4.2}, 3.0, 4.2))\n\n}\n```\n\n#### Output\n\n```\n[3]\n[1 2]\n[1 2]\n[1 2.2]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Wrap](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L286\u003e)\n\n```go\nfunc Wrap[T ~string](str T, token string) T\n```\n\nWrap a string with the specified token.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(Unwrap(\"'abc'\", \"'\"))\n\tfmt.Println(Unwrap(\"*abc*\", \"*\"))\n\tfmt.Println(Unwrap(\"*a*bc*\", \"*\"))\n\tfmt.Println(Unwrap(\"''abc''\", \"''\"))\n\tfmt.Println(Unwrap(\"\\\"abc\\\"\", \"\\\"\"))\n\n}\n```\n\n#### Output\n\n```\nabc\nabc\na*bc\nabc\nabc\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [WrapAllRune](\u003chttps://github.com/esimov/gogu/blob/master/string.go#L309\u003e)\n\n```go\nfunc WrapAllRune[T ~string](str T, token string) T\n```\n\nWrapAllRune is like Wrap, only that it's applied over runes instead of strings.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tfmt.Println(WrapAllRune(\"abc\", \"\"))\n\tfmt.Println(WrapAllRune(\"abc\", \"'\"))\n\tfmt.Println(WrapAllRune(\"abc\", \"*\"))\n\tfmt.Println(WrapAllRune(\"abc\", \"-\"))\n\n}\n```\n\n#### Output\n\n```\nabc\n'a''b''c'\n*a**b**c*\n-a--b--c-\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## func [Zip](\u003chttps://github.com/esimov/gogu/blob/master/slice.go#L486\u003e)\n\n```go\nfunc Zip[T any](slices ...[]T) [][]T\n```\n\nZip iteratively merges together the values of the slice parameters with the values at the corresponding position.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tres := Zip([]any{\"one\", \"two\"}, []any{1, 2})\n\tfmt.Println(res)\n\n}\n```\n\n#### Output\n\n```\n[[one 1] [two 2]]\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## type [Bound](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L180-L182\u003e)\n\n```go\ntype Bound[T constraints.Signed] struct {\n    Min, Max T\n}\n```\n\n### func \\(Bound\\[T\\]\\) [Enclose](\u003chttps://github.com/esimov/gogu/blob/master/find.go#L185\u003e)\n\n```go\nfunc (b Bound[T]) Enclose(nth T) bool\n```\n\nEnclose checks if an element is inside the bounds.\n\n## type [CompFn](\u003chttps://github.com/esimov/gogu/blob/master/generic.go#L8\u003e)\n\nCompFn is a generic function type for comparing two values.\n\n```go\ntype CompFn[T any] func(a, b T) bool\n```\n\n### func [NewMemoizer](\u003chttps://github.com/esimov/gogu/blob/master/memoize.go#L19\u003e)\n\n```go\nfunc NewMemoizer[T ~string, V any](expiration, cleanup time.Duration) *Memoizer[T, V]\n```\n\nNewMemoizer instantiates a new Memoizer.\n\n### func \\(Memoizer\\[T, V\\]\\) [Memoize](\u003chttps://github.com/esimov/gogu/blob/master/memoize.go#L32\u003e)\n\n```go\nfunc (m Memoizer[T, V]) Memoize(key T, fn func() (*cache.Item[V], error)) (*cache.Item[V], error)\n```\n\nMemoize returns the item under a specific key instantly in case the key exists, otherwise returns the results of the given function, making sure that only one execution is in\\-flight for a given key at a time.\n\nThis method is useful for caching the result of a time\\-consuming operation when is more important to return a slightly outdated result, than to wait for an operation to complete before serving it.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tm := NewMemoizer[string, any](time.Second, time.Minute)\n\n\tsampleItem := map[string]any{\n\t\t\"foo\": \"one\",\n\t\t\"bar\": \"two\",\n\t\t\"baz\": \"three\",\n\t}\n\n\texpensiveOp := func() (*cache.Item[any], error) {\n\t\t// Here we are simulating an expensive operation.\n\t\ttime.Sleep(500 * time.Millisecond)\n\n\t\tfoo := FindByKey(sampleItem, func(key string) bool {\n\t\t\treturn key == \"foo\"\n\t\t})\n\t\tm.Cache.MapToCache(foo, cache.DefaultExpiration)\n\n\t\titem, err := m.Cache.Get(\"foo\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn item, nil\n\t}\n\n\tfmt.Println(m.Cache.List())\n\t// Caching the result of some expensive fictive operation result.\n\tdata, _ := m.Memoize(\"key1\", expensiveOp)\n\tfmt.Println(len(m.Cache.List()))\n\n\titem, _ := m.Cache.Get(\"key1\")\n\tfmt.Println(item.Val())\n\n\t// Serving the expensive operation result from the cache. This should return instantly.\n\t// If it would invoked the expensiveOp function this would be introduced a 500 millisecond latency.\n\tdata, _ = m.Memoize(\"key1\", expensiveOp)\n\tfmt.Println(data.Val())\n\n}\n```\n\n#### Output\n\n```\nmap[]\n2\none\none\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## type [Number](\u003chttps://github.com/esimov/gogu/blob/master/map.go#L12-L14\u003e)\n\nNumber is a custom type set of constraints extending the Float and Integer type set from the experimental constraints package.\n\n```go\ntype Number interface {\n    // contains filtered or unexported methods\n}\n```\n\n## type [RType](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L68-L70\u003e)\n\nRType is a generic struct type used as method receiver on retry operations.\n\n```go\ntype RType[T any] struct {\n    Input T\n}\n```\n\n### func \\(RType\\[T\\]\\) [Retry](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L74\u003e)\n\n```go\nfunc (v RType[T]) Retry(n int, fn func(T) error) (int, error)\n```\n\nRetry tries to invoke the callback function \\`n\\` times. It runs until the number of attempts is reached or the returned value of the callback function is nil.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tn := 2\n\tidx := 0\n\tForEach([]string{\"one\", \"two\", \"three\"}, func(val string) {\n\t\trt := RType[string]{Input: val}\n\t\tattempts, e := rt.Retry(n, func(elem string) (err error) {\n\t\t\tif len(elem)%3 != 0 {\n\t\t\t\terr = fmt.Errorf(\"retry failed: number of %d attempts exceeded\", n)\n\t\t\t}\n\t\t\treturn err\n\t\t})\n\t\tswitch idx {\n\t\tcase 0:\n\t\t\tfmt.Println(attempts)\n\t\tcase 1:\n\t\t\tfmt.Println(attempts)\n\t\tcase 2:\n\t\t\tfmt.Println(attempts)\n\t\t\tfmt.Println(e)\n\t\t}\n\t\tidx++\n\t})\n\n}\n```\n\n#### Output\n\n```\n0\n0\n2\nretry failed: number of 2 attempts exceeded\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n### func \\(RType\\[T\\]\\) [RetryWithDelay](\u003chttps://github.com/esimov/gogu/blob/master/func.go#L96\u003e)\n\n```go\nfunc (v RType[T]) RetryWithDelay(n int, delay time.Duration, fn func(time.Duration, T) error) (time.Duration, int, error)\n```\n\nRetryWithDelay tries to invoke the callback function \\`n\\` times, but with a delay between each call. It runs until the number of attempts is reached or the error return value of the callback function is nil.\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n```go\n{\n\tn := 5\n\t// In this example we are simulating an external service. In case the response time\n\t// exceeds a certain time limit we stop retrying and we are returning an error.\n\tservices := []struct {\n\t\tservice string\n\t\ttime    time.Duration\n\t}{\n\t\t{service: \"AWS1\"},\n\t\t{service: \"AWS2\"},\n\t}\n\n\ttype Service[T ~string] struct {\n\t\tService T\n\t\tTime    time.Duration\n\t}\n\n\tfor _, srv := range services {\n\t\tr := random(1, 10)\n\t\t// Here we are simulating the response time of the external service\n\t\t// by generating some random duration between 1ms and 10ms.\n\t\t// All the test should pass because all of the responses are inside the predefined limit (10ms).\n\t\tservice := Service[string]{\n\t\t\tService: srv.service,\n\t\t\tTime:    time.Duration(r) * time.Millisecond,\n\t\t}\n\t\trtyp := RType[Service[string]]{\n\t\t\tInput: service,\n\t\t}\n\n\t\td, att, e := rtyp.RetryWithDelay(n, 20*time.Millisecond, func(d time.Duration, srv Service[string]) (err error) {\n\t\t\tif srv.Time.Milliseconds() \u003e 10 {\n\t\t\t\terr = fmt.Errorf(\"retry failed: service time exceeded\")\n\t\t\t}\n\t\t\treturn err\n\t\t})\n\t\tfmt.Println(e)\n\t\tfmt.Println(att)\n\t\tfmt.Println(d.Milliseconds())\n\t}\n\n}\n```\n\n#### Output\n\n```\n\u003cnil\u003e\n0\n0\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## 🤝 Contributing\n- Request new features or fix [open issues](https://github.com/esimov/gogu/issues)\n- Fork the project and make [pull requests](https://github.com/esimov/gogu/pulls)\n\n## Author\n* Endre Simo ([@simo_endre](https://twitter.com/simo_endre))\n\n## License\nCopyright © 2022 Endre Simo\n\nThis software is distributed under the MIT license. See the [LICENSE](https://github.com/esimov/gogu/blob/master/LICENSE) file for the full license text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesimov%2Fgogu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesimov%2Fgogu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesimov%2Fgogu/lists"}