{"id":16931627,"url":"https://github.com/jesseduffield/generics","last_synced_at":"2025-08-21T23:05:27.199Z","repository":{"id":40497450,"uuid":"471327544","full_name":"jesseduffield/generics","owner":"jesseduffield","description":"extensions on the official Go generics packages","archived":false,"fork":false,"pushed_at":"2022-03-20T04:38:37.000Z","size":64,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T11:04:25.490Z","etag":null,"topics":[],"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/jesseduffield.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-18T10:38:20.000Z","updated_at":"2024-05-09T15:19:09.000Z","dependencies_parsed_at":"2022-08-26T15:54:23.665Z","dependency_job_id":null,"html_url":"https://github.com/jesseduffield/generics","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesseduffield%2Fgenerics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesseduffield%2Fgenerics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesseduffield%2Fgenerics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesseduffield%2Fgenerics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jesseduffield","download_url":"https://codeload.github.com/jesseduffield/generics/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244959409,"owners_count":20538625,"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":[],"created_at":"2024-10-13T20:44:24.311Z","updated_at":"2025-08-21T23:05:27.186Z","avatar_url":"https://github.com/jesseduffield.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Generics\n\nThis is a repo for some helper methods/structs that involve generics (added in Go 1.18).\n\n## slices package\n\nThis package contains all the functions in the official slices [package](https://pkg.go.dev/golang.org/x/exp/slices#Insert) but adds extra functions as well, resulting in a superset of the official API. Any official functions are just forwarded to the official implementations. This allows you to use this package wherever you would otherwise use the official slices package.\n\nAs the official slices package evolves, so too will this package. If a function is added to the official package that does basically the same thing as a function from this package, we'll replace our function for the official function.\n\nHere are the newly added functions.\n\n```go\nfunc Some[T any](slice []T, test func(T) bool) bool\nfunc Every[T any](slice []T, test func(T) bool) bool\nfunc ForEach[T any](slice []T, f func(T))\nfunc ForEachWithIndex[T any](slice []T, f func(T, int))\nfunc TryForEach[T any](slice []T, f func(T) error) error\nfunc TryForEachWithIndex[T any](slice []T, f func(T, int) error) error\nfunc Map[T any, V any](slice []T, f func(T) V) []V\nfunc MapWithIndex[T any, V any](slice []T, f func(T, int) V) []V\nfunc TryMap[T any, V any](slice []T, f func(T) (V, error)) ([]V, error)\nfunc TryMapWithIndex[T any, V any](slice []T, f func(T, int) (V, error)) ([]V, error)\nfunc MapInPlace[T any](slice []T, f func(T) T)\nfunc Filter[T any](slice []T, test func(T) bool) []T\nfunc FilterWithIndex[T any](slice []T, f func(T, int) bool) []T\nfunc TryFilter[T any](slice []T, test func(T) (bool, error)) ([]T, error)\nfunc TryFilterWithIndex[T any](slice []T, test func(T, int) (bool, error)) ([]T, error)\nfunc FilterInPlace[T any](slice []T, test func(T) bool) []T\nfunc FilterMap[T any, E any](slice []T, test func(T) (E, bool)) []E\nfunc TryFilterMap[T any, E any](slice []T, test func(T) (E, bool, error)) ([]E, error)\nfunc TryFilterMapWithIndex[T any, E any](slice []T, test func(T, int) (E, bool, error))\nfunc FlatMap[T any, V any](slice []T, f func(T) []V) []V\nfunc Flatten[T any](slice [][]T) []T\nfunc Find[T any](slice []T, f func(T) bool) (T, bool)\nfunc FindMap[T any, V any](slice []T, f func(T) (V, bool)) (V, bool)\nfunc Reverse[T any](slice []T) []T\nfunc ReverseInPlace[T any](slice []T)\nfunc Prepend[T any](slice []T, values ...T) []T\nfunc Remove[T any](slice []T, index int) []T\nfunc Move[T any](slice []T, fromIndex int, toIndex int) []T\nfunc Swap[T any](slice []T, index1 int, index2 int)\nfunc Concat[T any](slice []T, values ...T) []T\nfunc ContainsFunc[T any](slice []T, f func(T) bool) bool\nfunc Pop[T any](slice []T) (T, []T)\nfunc Shift[T any](slice []T) (T, []T)\nfunc Partition[T any](slice []T, test func(T) bool) ([]T, []T)\nfunc MaxBy[T any, V constraints.Ordered](slice []T, f func(T) V) V\nfunc MinBy[T any, V constraints.Ordered](slice []T, f func(T) V) V\n```\n\nThere's a good chance I'll have the Map/Filter functions take an index argument unconditionally and leave it to the user to omit that if they want. That will cut down on the number of functions here, but add some boilerplate. I'm currently comparing both approaches on a sizable repo to help decide.\n\n## list package\n\nThis package provides a List struct which wraps a slice and gives you access to all the above functions, with a couple exceptions. For example, there's no Map method because go does not support type parameters on struct methods.\n\n## set package\n\nThis package provides a Set struct with the following methods:\n\n```go\nAdd(values ...T)\nAddSlice(slice []T)\nRemove(value T)\nRemoveSlice(slice []T)\nIncludes(value T) bool\nLen() int\nToSlice() []T\n```\n\n## orderedset package\n\nThis package provides an OrderedSet struct with the following methods:\n\n```go\nAdd(values ...T)\nAddSlice(slice []T)\nRemove(value T)\nRemoveSlice(slice []T)\nIncludes(value T) bool\nLen() int\nToSliceFromOldest() []T\nToSliceFromNewest() []T\n```\n\nThe difference to Set is that the insertion order of the values is preserved.\n\n## maps package\n\nProvides some helper methods for maps:\n\n```go\nfunc Keys[Key comparable, Value any](m map[Key]Value) []Key\nfunc Values[Key comparable, Value any](m map[Key]Value) []Value\nfunc TransformValues[Key comparable, Value any, NewValue any\nfunc TransformKeys[Key comparable, Value any, NewKey comparable](m map[Key]Value, fn func(Key) NewKey) map[NewKey]Value\nfunc MapToSlice[Key comparable, Value any, Mapped any](m map[Key]Value, f func(Key, Value) Mapped) []Mapped\nfunc Filter[Key comparable, Value any](m map[Key]Value, f func(Key, Value) bool) map[Key]Value\n```\n\n## Alternatives\n\nCheck out https://github.com/samber/lo for some more generic helper functions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjesseduffield%2Fgenerics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjesseduffield%2Fgenerics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjesseduffield%2Fgenerics/lists"}