{"id":22885097,"url":"https://github.com/rendis/devtoolkit","last_synced_at":"2025-03-31T18:22:20.427Z","repository":{"id":175953362,"uuid":"654761857","full_name":"rendis/devtoolkit","owner":"rendis","description":"devtoolkit is a utility library designed to streamline and enhance the daily development tasks of programmers. ","archived":false,"fork":false,"pushed_at":"2024-12-24T16:27:02.000Z","size":165,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-06T22:42:35.997Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/rendis.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-16T22:26:36.000Z","updated_at":"2024-12-24T16:27:06.000Z","dependencies_parsed_at":"2024-06-28T23:19:56.780Z","dependency_job_id":"88af5b4c-e999-4b4c-b1e7-943ad120c7b7","html_url":"https://github.com/rendis/devtoolkit","commit_stats":null,"previous_names":["rendis/devtoolkit"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rendis%2Fdevtoolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rendis%2Fdevtoolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rendis%2Fdevtoolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rendis%2Fdevtoolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rendis","download_url":"https://codeload.github.com/rendis/devtoolkit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246515307,"owners_count":20790029,"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-12-13T19:31:47.207Z","updated_at":"2025-03-31T18:22:20.402Z","avatar_url":"https://github.com/rendis.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Devtoolkit\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/rendis/devtoolkit)](https://goreportcard.com/report/github.com/rendis/devtoolkit)\n[![Go Reference](https://pkg.go.dev/badge/github.com/rendis/devtoolkit.svg)](https://pkg.go.dev/github.com/rendis/devtoolkit)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Release](https://img.shields.io/github/release/rendis/devtoolkit.svg?style=flat-square)](https://github.com/rendis/devtoolkit/releases)\n\nDevtoolkit is a powerful and ever-expanding toolkit designed to streamline daily tasks in Golang software development. \nWithin this library, you'll find an array of features, such as tools for working with yml or json prop files, slices, handling generic objects, managing concurrency, and more. \nAs Devtoolkit continues to evolve, it will encompass even more functionalities to cater to a variety of programming needs.\n\n## Table of Contents\n- [Devtoolkit](#devtoolkit)\n    * [Installation](#installation)\n    * [Usage](#usage)\n        + [Concurrent solutions](#concurrent-solutions)\n            - [Running concurrent functions](#running-concurrent-functions)\n            - [Running concurrent workers](#running-concurrent-workers)\n        + [Load properties from a file (JSON/YAML) with environment variable injections and validations](#load-properties-from-a-file-with-environment-variable-injections-and-validations)\n        + [Resilience](#resilience)\n            - [RetryOperation](#retryoperation)\n        + [Design Patterns](#design-patterns)\n            - [Process Chain](#process-chain)\n        + [Data structures](#data-structures)\n            - [Pair](#pair)\n            - [Triple](#triple)\n        + [Readers](#readers)\n            - [CSV Reader](#csv-reader)\n        + [Generators](#generators)\n            - [struct-guard](#struct-guard)\n        + [Working with Generic Objects](#working-with-generic-objects)\n            - [ToPtr](#toptr)\n            - [IsZero](#iszero)\n            - [StructToMap](#structtomap)\n            - [MapToStruct](#maptostruct)\n            - [CastToPointer](#casttopointer)\n            - [IfThenElse](#ifthenelse)\n            - [IfThenElseFn](#ifthenelsefn)\n            - [DefaultIfNil](#defaultifnil)\n            - [ZeroValue](#zerovalue)\n            - [ToInt](#toint)\n            - [ToFloat64](#tofloat64)\n            - [StrToStruct](#strtostruct)\n        + [Working with Slices](#working-with-slices)\n            - [Contains](#contains)\n            - [ContainsWithPredicate](#containswithpredicate)\n            - [IndexOf](#indexof)\n            - [IndexOfWithPredicate](#indexofwithpredicate)\n            - [LastIndexOf](#lastindexof)\n            - [LastIndexOfWithPredicate](#lastindexofwithpredicate)\n            - [Remove](#remove)\n            - [RemoveWithPredicate](#removewithpredicate)\n            - [RemoveAll](#removeall)\n            - [RemoveAllWithPredicate](#removeallwithpredicate)\n            - [RemoveAt](#removeat)\n            - [RemoveRange](#removerange)\n            - [RemoveIf](#removeif)\n            - [Filter](#filter)\n            - [FilterNot](#filternot)\n            - [Map](#map)\n            - [RemoveDuplicates](#removeduplicates)\n            - [Reverse](#reverse)\n            - [Difference](#difference)\n            - [Intersection](#intersection)\n            - [Union](#union)\n            - [GetMapKeys](#getmapkeys)\n            - [GetMapValues](#getmapvalues)\n    * [Contributions](#contributions)\n    * [License](#license)\n\n## Installation\n\n```\ngo get github.com/rendis/devtoolkit\n```\n\n## Usage\n\n### Concurrent solutions\n\n#### ConcurrentExec\n\n`ConcurrentExec` is a utility for executing a series of functions concurrently.\n\n```go\nvar fns []devtoolkit.ConcurrentFn\n\nfns = append(fns, func(ctx context.Context) (any, error) {\n   // Implement function logic\n   return \"Result1\", nil\n})\n\nfns = append(fns, func(ctx context.Context) (any, error) {\n   // Implement function logic\n   return \"Result2\", nil\n})\n\nctx := context.Background()\nce, err := devtoolkit.NewConcurrentExec().ExecuteFns(ctx, fns...)\n\nif err != nil {\n   fmt.Println(err)\n}\n\n// errors is a slice of errors returned by the functions, where each index corresponds to the function at the same index in the fns slice\nerrors := ce.Errors()\nfor _, err := range errors {\n   if err != nil {\n      fmt.Println(err)\n   }\n}\n\n// results is a slice of results returned by the functions, where each index corresponds to the function at the same index in the fns slice\n// Note: results are of type any, so you'll need to cast them to the appropriate type\nresults := ce.Results()\nfor _, res := range results {\n   fmt.Println(res)\n}\n```\n\nNote: This example does not include error handling, be sure to do so in your implementations.\n\n#### ConcurrentWorkers\n\n`ConcurrentWorkers` is a utility for executing a series of functions concurrently using a pool of workers.\n\n```go\nvar maxWorkers = 5\nvar cw = NewConcurrentWorkers(maxWorkers)\n\nfor i := 0; i \u003c 10; i++ {\n   cw.Execute(func() {\n      // do something cool\n   })\n}\n\n// Stop the workers with an error\ncw.Stop(fmt.Errorf(\"Something went wrong\"))\n\n// Stop the workers without an error\ncw.Stop(nil)\n\n// Wait for all workers to finish\ncw.Wait()\n```\n\n#### ConcurrentManager\n\n`ConcurrentManager` is a struct that dynamically manages a pool of workers within set limits. \nIt adjusts worker count based on load, offering functions to allocate, release, and wait for workers, \noptimizing concurrent task handling.\n\n```go\n// NewConcurrentManager creates a new instance of ConcurrentManager with specified parameters.\n// It ensures that the provided parameters are within acceptable ranges and initializes the manager.\nfunc NewConcurrentManager(minWorkers, maxWorkers int, workerIncreaseRate float64, timeIncreasePeriod time.Duration) *ConcurrentManager\n\n// Allocate requests a new worker to be allocated.\n// It blocks if the maximum number of workers has been reached, until a worker is released.\nfunc (c *ConcurrentManager) Allocate()\n\n// Release frees up a worker, making it available for future tasks.\n// It only releases a worker if the release condition is met, ensuring resources are managed efficiently.\nfunc (c *ConcurrentManager) Release()\n\n// Wait blocks until all workers have finished their tasks.\n// It ensures that all resources are properly cleaned up before shutting down or reinitializing the manager.\nfunc (c *ConcurrentManager) Wait()\n```\n\n\n#### AtomicNumber\n\n`AtomicNumber` is a utility for managing an number atomically.\n\n```go\n// initialize an atomic number with default value 0\nvar atomic AtomicNumber[int]\n\natomic.Get() // get the current value\natomic.Set(5) // set the value to 5\natomic.Increment() // increment the value by 1\natomic.IncrementBy(10) // add 10 to the value\natomic.IncrementAndGet() // increment the value by 1 and return the new value\natomic.IncrementByAndGet(10) // add 10 to the value and return the new value\nvar incremented = atomic.IncrementIf(func(v int) {return v \u003e 0}) // increment the value by 1 if the condition is met\nvar incrementedBy = atomic.IncrementByIf(10, func(v int) {return v \u003e 0}) // add 10 to the value if the condition is met\n\n// same functions are available for decrementing the value\natomic.Decrement() // decrement the value by 1\n...\n```\n\n\n\n---\n\n### Load properties from a file with environment variable injections and validations\n\nUtility functions for loading configuration properties from JSON or YAML files.\nThis functionality supports the injection of environment variables directly into the configuration properties.\n\n`LoadPropFile` supports field validation using struct tags provided by the [go-playground/validator](https://github.com/go-playground/validator/v10) library.\n\nYou can register your own custom validators using the `RegisterCustomValidator` function.\n\n`devtoolkit` provides the following built-in validators:\n- `trimmed-non-empty` - checks whether a string is not empty after trimming whitespace\n \n```yaml\ndbConfig:\n  host: ${DB_HOST}\n  port: ${DB_PORT}\n  username: ${DB_USERNAME}\n  password: ${DB_PASSWORD}\n  description: \"YAML config file\"\n```\n\n```json\n{\n  \"dbConfig\": {\n    \"host\": \"${DB_HOST}\",\n    \"port\": \"${DB_PORT}\",\n    \"username\": \"${DB_USERNAME}\",\n    \"password\": \"${DB_PASSWORD}\",\n    \"description\": \"JSON config file\"\n  }\n}\n```\n\n```go\ntype Config struct {\n    DBConfig `json:\"dbConfig\" yaml:\"dbConfig\" validate:\"required\"`\n}\n\ntype DBConfig struct {\n    Host string `json:\"host\" yaml:\"host\" validate:\"required\"`\n    Port int `json:\"port\" yaml:\"port\" validate:\"required,min=1,max=65535\"`\n    Username string `json:\"username\" yaml:\"username\" validate:\"required,trimmed-non-empty\"`\n    Password string `json:\"password\" yaml:\"password\" validate:\"required,trimmed-non-empty\"`\n    Description string `json:\"description\" yaml:\"description\" validate:\"required\"`\n}\n\nfunc (p *Config) SetDefaults() {\n    p.DBConfig.Host = \"localhost\"\n    p.DBConfig.Port = 3306\n}\n\nfunc trimmedNonEmpty(fl validator.FieldLevel) bool {\n    s := fl.Field().String()\n    trimmed := strings.TrimSpace(s)\n    return len(trimmed) \u003e 0\n}\n\ncfg := \u0026Config{}\nprops := []devtoolkit.ToolKitProp{cfg}\ndevtoolkit.RegisterCustomValidator(\"trimmed-non-empty\", trimmedNonEmpty)\nerr := devtoolkit.LoadPropFile(\"config.json\", props)\n\n```\n\n---\n\n### Resilience\n\nUtility functions and patterns to ensure resilient operation execution.\n\n#### RetryOperation\n\nThe `RetryOperation` function retries an operation for a specified number of times with optional exponential backoff. It's useful when operations have a tendency to fail temporarily and may succeed on a subsequent attempt.\n\n```go\ntype ResilienceOptions struct {\n    MaxRetries       int                     // indicates the maximum number of retries. Default is 3.\n    WaitTime         time.Duration           // indicates the wait time between retries. Default is 100ms.\n    Backoff          bool                    // indicates whether to use exponential backoff. Default is false.\n    RawError         bool                    // indicates whether to return the raw error or wrap it in a new error. Default is false.\n    IsIgnorableErrorHandler func(error) bool // indicates whether to ignore the error or not. Default is nil.\n    ReturnIgnorable  bool                    // indicates whether to return the ignorable error or not. Default is false.\n}\n\n\nfunc NewResilience(options *ResilienceOptions) (Resilience, error)\n```\n\nExample:\n```go\noperation := func() error {\n\treturn networkCall() // Some hypothetical network operation\n}\noptions := \u0026devtoolkit.ResilienceOptions{\n\tMaxRetries: 3, \n\tWaitTime:   2 * time.Second,\n\tBackoff:    true,\n}\n\nresilienceHandler, err := devtoolkit.NewResilience(options)\n\nif err != nil {\n\tpanic(err)\n}\n\nerr = resilienceHandler.RetryOperation(operation) // wrapped error returned\n\nif err != nil {\n\tfmt.Println(\"Operation failed.\", err)\n} else {\n\tfmt.Println(\"Operation succeeded!\")\n}\n```\n\nWith the `RetryOperation` function, users can easily add resiliency to their operations and ensure that temporary failures don't lead to complete system failures.\n\n---\n\n### Design Patterns\n\n#### Process Chain\n`ProcessChain` is an implementation that enables the orderly execution of operations on data within a Go application.\nLeveraging the \"Chain of Responsibility\" and \"Command\" design patterns, it allows for the addition of operations (links)\nand an optional save step to ensure data integrity after each operation. Ideal for scenarios requiring a series of\nactions on data with the flexibility to add, remove, or modify steps as needed.\n\n```go\ntype ProcessChain[T any] interface {\n    AddLink(string, LinkFn[T]) error\n    SetSaveStep(SaveStep[T])\n    GetChain() []string\n    Execute(context.Context, T) ([]string, error)\n    ExecuteWithIgnorableLinks(context.Context, T, []string) ([]string, error)\n}\n\nfunc NewProcessChain[T any](opts *ProcessChainOptions) ProcessChain[T]\n```\n\nExample:\n```go\ntype Data struct {\n    // Your data fields here\n}\n\nfunc step1(d Data) error {\n    // Define a process operation\n}\n\nfunc step2(d Data) error {\n    // Define a process operation\n}\n\nfunc saveData(d Data) error {\n    // Define a save operation\n}\n\nchain := NewProcessChain[Data]()\nchain.AddLink(\"step1\", step1)\nchain.AddLink(\"step2\", step2)\nchain.SetSaveStep(saveData)\nerr := chain.Execute(Data{})\n```\n---\n\n### Working with Generic Objects\n\n#### ToPtr\n\nThe `ToPtr` function takes a value of any type and returns a pointer to it.\n\n```go\nval := 5\nptr := devtoolkit.ToPtr(val)\nfmt.Println(*ptr) // Returns 5\n```\n\n#### IsZero\n\nThe `IsZero` function checks whether a value is the zero value of its type.\n\n```go\nfmt.Println(devtoolkit.IsZero(0)) // Returns true\nfmt.Println(devtoolkit.IsZero(1)) // Returns false\nfmt.Println(devtoolkit.IsZero(\"\")) // Returns true\n```\n\n#### StructToMap\n\nThe `StructToMap` function converts a struct to a `map[string]any`.\n\n```go\ntype Person struct {\n\tName  string `json:\"name\"`\n\tAge   int    `json:\"age\"`\n\tEmail string `json:\"email\"`\n}\n\np := Person{\n    Name:  \"John\",\n    Age:   30,\n    Email: \"john@example.com\",\n}\n\npersonMapData, err := devtoolkit.StructToMap(p)\n```\n\n\n#### MapToStruct\n\nThe `MapToStruct` function converts a `map[string]any` to a pointer to a struct.\n\n```go\n// personMapData is a map[string]any containing the data of a Person struct, see StructToMap example\nptrToNewPerson, err := devtoolkit.MapToStruct[Person](personMapData)\n```\n\n#### CastToPointer\n`CastToPointer` casts a value to a pointer of the same type.\n\n```go\nfunc CastToPointer[T any](v any) (*T, bool)\n```\n\nRules:\n- v must be a pointer.\n- if v not a pointer, returns false.\n- if v is nil, returns false.\n- if v is a pointer but not of the given type, returns false.\n- if v is a pointer of the given type, returns true.\n\n\n#### IfThenElse\n`IfThenElse` returns the first value if the condition is true, otherwise it returns the second value.\n\n```go\nfunc IfThenElse[T any](condition bool, first, second T) T\n```\n\n#### IfThenElseFn\n`IfThenElseFn` returns the first value if the condition is true, otherwise it returns the result of the second value.\n\n```go\nfunc IfThenElseFn[T any](condition bool, first T, second func() T) T\n```\n\n#### DefaultIfNil\n`DefaultIfNil` returns the first value if it is not nil, otherwise it returns the second value.\n\n```go\nfunc DefaultIfNil[T any](first *T, second T) T\n```\n\n#### ZeroValue\n`ZeroValue` returns the zero value of a type.\n\n```go\nfunc ZeroValue[T any]() T\n```\n\n#### ToInt\n`ToInt` converts a value to an int.\n\n```go\nfunc ToInt(value any) (int, bool)\n```\n\n\n#### ToFloat64\n`ToFloat64` converts a value to a float64.\n\n```go\nfunc ToFloat64(value any) (float64, bool)\n```\n\n\n#### StrToStruct\n`StrToStruct` converts a string to a struct.\n\n```go\nfunc StrToStruct[T any](s string) (*T, error)\n```\n\n---\n\n### Data structures\n\n#### Pair\n\nThe `Pair` type represents a pair of values.\n\n```go\ntype Pair[F any, S any] struct {\n    First  F\n    Second S\n}\n```\n\n#### Triple\n\nThe `Triple` type represents a triple of values.\n\n```go\ntype Triple[F any, S any, T any] struct {\n    First  F\n    Second S\n    Third  T\n}\n```\n\n---\n\n### Readers\n\n#### CSV Reader\n\nThe CSV reader provides a simple and efficient way to read CSV files in Go.\n\nMore details can be found in the [CSV Reader documentation](reader/csv/README.md).\n\n---\n\n### Generators\n\n#### struct-guard\n\nThe struct-guard tool generates wrapper structs in Go for tracking changes to the fields of the original struct.\n\nMore details can be found in the [struct-generator documentation](generator/struct-guard/README.md).\n\n---\n\n### Working with Slices\n\nCommon utility functions for working with slices.\n\n#### Contains\n\nThe `Contains` function checks whether a slice contains an item. The item must be comparable.\n\n```go\nfunc Contains[T comparable](slice []T, item T) bool\n```\n\nExample:\n```go\nslice := []int{1, 2, 3}\nitem := 2\nfmt.Println(devtoolkit.Contains(slice, item)) // Returns true\n```\n\n#### ContainsWithPredicate\n\nThe `ContainsWithPredicate` function checks whether a slice contains an item using a predicate to compare items.\n\n```go\nfunc ContainsWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool\n```\n\nExample:\n```go\nslice := []int{1, 2, 3}\nitem := 2\npredicate := func(a, b int) bool { return a == b }\nfmt.Println(devtoolkit.ContainsWithPredicate(slice, item, predicate)) // Returns true\n```\n\n#### IndexOf\n\n`IndexOf` returns the index of the first instance of an item in a slice, or -1 if the item is not present in the slice.\n\n```go\nfunc IndexOf[T comparable](slice []T, item T) int\n```\n\nExample:\n\n```go\nindex := IndexOf([]int{1, 2, 3, 2, 1}, 2)\nfmt.Println(index) // Output: 1\n```\n\n#### IndexOfWithPredicate\n\n`IndexOfWithPredicate` returns the index of the first instance of an item in a slice, or -1 if the item is not present in the slice. It uses a predicate function to compare items.\n\n```go\nfunc IndexOfWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) int\n```\n\nExample:\n\n```go\nindex := IndexOfWithPredicate([]string{\"apple\", \"banana\", \"cherry\"}, \"APPLE\", strings.EqualFold)\nfmt.Println(index) // Output: 0\n```\n\n#### LastIndexOf\n\n`LastIndexOf` returns the index of the last instance of an item in a slice, or -1 if the item is not present in the slice.\n\n```go\nfunc LastIndexOf[T comparable](slice []T, item T) int\n```\n\nExample:\n\n```go\nindex := LastIndexOf([]int{1, 2, 3, 2, 1}, 2)\nfmt.Println(index) // Output: 3\n```\n\n#### LastIndexOfWithPredicate\n\n`LastIndexOfWithPredicate` returns the index of the last instance of an item in a slice, or -1 if the item is not present in the slice. It uses a predicate function to compare items.\n\n```go\nfunc LastIndexOfWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) int\n```\n\nExample:\n\n```go\nindex := LastIndexOfWithPredicate([]string{\"apple\", \"banana\", \"cherry\", \"apple\"}, \"APPLE\", strings.EqualFold)\nfmt.Println(index) // Output: 3\n```\n\n#### Remove\n\n`Remove` removes the first instance of an item from a slice, if present. It returns true if the item was removed, false otherwise.\n\n```go\nfunc Remove[T comparable](slice []T, item T) bool\n```\n\nExample:\n\n```go\nremoved := Remove([]int{1, 2, 3, 2, 1}, 2)\nfmt.Println(removed) // Output: true\n```\n\n#### RemoveWithPredicate\n\n`RemoveWithPredicate` removes the first instance of an item from a slice, if present. It uses a predicate function to compare items. It returns true if the item was removed, false otherwise.\n\n```go\nfunc RemoveWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool\n```\n\nExample:\n\n```go\nremoved := RemoveWithPredicate([]string{\"apple\", \"banana\", \"cherry\"}, \"APPLE\", strings.EqualFold)\nfmt.Println(removed) // Output: true\n```\n\n#### RemoveAll\n\n`RemoveAll` removes all instances of an item from a slice, if present. It returns true if the item was removed, false otherwise.\n\n```go\nfunc RemoveAll[T comparable](slice []T, item T) bool\n```\n\nExample:\n\n```go\nremoved := RemoveAll([]int{1, 2, 3, 2, 1}, 2)\nfmt.Println(removed) // Output: true\n```\n\n#### RemoveAllWithPredicate\n\n`RemoveAllWithPredicate` removes all instances of an item from a slice, if present. It uses a predicate function to compare items. It returns true if the item was removed, false otherwise.\n\n```go\nfunc RemoveAllWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool\n```\n\nExample:\n\n```go\nremoved := RemoveAllWithPredicate([]string{\"apple\", \"banana\", \"cherry\", \"apple\"}, \"APPLE\", strings.EqualFold)\nfmt.Println(removed) // Output: true\n```\n\n#### RemoveAt\n\n`RemoveAt` removes the item at a given index from a slice. It returns true if the item was removed, false otherwise.\n\n```go\nfunc RemoveAt[T any](slice []T, index int) bool\n```\n\nExample:\n\n```go\nremoved := RemoveAt([]int{1, 2, 3}, 1)\nfmt.Println(removed) // Output: true\n```\n\n#### RemoveRange\n\n`RemoveRange` removes the items in a given range from a slice. It returns true if items were removed, false otherwise.\n\n```go\nfunc RemoveRange[T any](slice []T, start, end int) bool\n```\n\nExample:\n\n```go\nremoved := RemoveRange([]int{1, 2, 3, 4, 5}, 1, 3)\nfmt.Println(removed) // Output: true\n```\n\n#### RemoveIf\n\n`RemoveIf` removes all items from a slice for which a predicate function returns true. It returns true if any items were removed, false otherwise.\n\n```go\nfunc RemoveIf[T any](slice []T, predicate func(T) bool) bool\n```\n\nExample:\n\n```go\nremoved := RemoveIf([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })\nfmt.Println(removed) // Output: true\n```\n\n#### Filter\n\n`Filter` returns a new slice containing all items from the original slice for which a predicate function returns true.\n\n```go\nfunc Filter[T any](slice []T, predicate func(T) bool) []T\n```\n\nExample:\n\n```go\nfiltered := Filter([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })\nfmt.Println(filtered) // Output: [2 4]\n```\n\n#### FilterNot\n\n`FilterNot` returns a new slice containing all items from the original slice for which a predicate function returns false.\n\n```go\nfunc FilterNot[T any](slice []T, predicate func(T) bool) []T\n```\n\nExample:\n\n```go\nfiltered := FilterNot([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })\nfmt.Println(filtered) // Output: [1 3 5]\n```\n\n\n#### Map\n\n`Map` applies a transformation function to all items in a slice and returns a new slice containing the results.\n\n```go\nfunc Map[T, R any](slice []T, mapper func(T) R) []R \n```\n\nExample:\n\n```go\nmapped := Map([]int{1, 2, 3}, func(n int) int { return n * 2 })\nfmt.Println(mapped) // Output: [2 4 6]\n```\n\n#### RemoveDuplicates\n\n`RemoveDuplicates` removes all duplicate items from a slice. It returns true if any items were removed, false otherwise.\n\n```go\nfunc RemoveDuplicates[T comparable](slice []T) bool\n```\n\nExample:\n\n```go\nremoved := RemoveDuplicates([]int{1, 2, 3, 2, 1})\nfmt.Println(removed) // Output: true\n```\n\n#### Reverse\n\n`Reverse` reverses the order of items in a slice.\n\n```go\nfunc Reverse[T any](slice []T)\n```\n\nExample:\n\n```go\ndata := []int{1, 2, 3}\nReverse(data)\nfmt.Println(data) // Output: [3 2 1]\n```\n\n#### Difference\n\n`Difference` returns a new slice containing all items from the original slice that are not present in the other slice.\n\n```go\nfunc Difference[T comparable](slice, other []T) []T\n```\n\nExample:\n\n```go\ndiff := Difference([]int{1, 2, 3, 4, 5}, []int{3, 4, 5, 6, 7})\nfmt.Println(diff) // Output: [1 2]\n```\n\n#### Intersection\n\n`Intersection` returns a new slice containing all items from the original slice that are also present in the other slice.\n\n```go\nfunc Intersection[T comparable](slice, other []T) []T\n```\n\nExample:\n\n```go\ninter := Intersection([]int{1, 2, 3, 4, 5}, []int{3, 4, 5, 6, 7})\nfmt.Println(inter) // Output: [3 4 5]\n```\n\n#### Union\n\n`Union` returns a new slice containing all unique items from both the original slice and the other slice.\n\n```go\nfunc Union[T comparable](slice, other []T) []T\n```\n\nExample:\n\n```go\nunion := Union([]int{1, 2, 3}, []int{3, 4, 5})\nfmt.Println(union) // Output: [1 2 3 4 5]\n```\n\n#### GetMapKeys\n`GetMapKeys` returns a slice of keys from a map.\n\n```go\nfunc GetMapKeys[K comparable, V any](m map[K]V) []K\n```\n\nExample:\n\n```go\nkeys := GetMapKeys(map[string]int{\"a\": 1, \"b\": 2})\nfmt.Println(keys) // Output: [a b]\n```\n\n\n#### GetMapValues\n`GetMapValues` returns a slice of values from a map.\n\n```go\nfunc GetMapValues[K comparable, V any](m map[K]V, removeDuplicates bool) []V\n```\n\nExample:\n\n```go\nvalues := GetMapValues(map[string]int{\"a\": 1, \"b\": 2, \"c\": 1}, false)\nfmt.Println(values) // Output: [1 2 1]\n\nvalues = GetMapValues(map[string]int{\"a\": 1, \"b\": 2, \"c\": 1}, true)\nfmt.Println(values) // Output: [1 2]\n```\n\n## Contributions\n\nContributions to this library are welcome. Please open an issue to discuss the enhancement or feature you would like to add, or just make a pull request.\n\n## License\n\nDevtoolkit is licensed under the MIT License. Please see the [LICENSE](LICENSE) file for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frendis%2Fdevtoolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frendis%2Fdevtoolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frendis%2Fdevtoolkit/lists"}