devtoolkit

package module
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2024 License: MIT Imports: 14 Imported by: 3

README

Devtoolkit

Go Report Card Go Reference Release

Devtoolkit is a powerful and ever-expanding toolkit designed to streamline daily tasks in Golang software development. Within 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. As Devtoolkit continues to evolve, it will encompass even more functionalities to cater to a variety of programming needs.

Table of Contents

Installation

go get github.com/rendis/devtoolkit

Usage

Concurrent solutions
ConcurrentExec

ConcurrentExec is a utility for executing a series of functions concurrently.

var fns []devtoolkit.ConcurrentFn

fns = append(fns, func(ctx context.Context) (any, error) {
   // Implement function logic
   return "Result1", nil
})

fns = append(fns, func(ctx context.Context) (any, error) {
   // Implement function logic
   return "Result2", nil
})

ctx := context.Background()
ce, err := devtoolkit.NewConcurrentExec().ExecuteFns(ctx, fns...)

if err != nil {
   fmt.Println(err)
}

// 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
errors := ce.Errors()
for _, err := range errors {
   if err != nil {
      fmt.Println(err)
   }
}

// 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
// Note: results are of type any, so you'll need to cast them to the appropriate type
results := ce.Results()
for _, res := range results {
   fmt.Println(res)
}

Note: This example does not include error handling, be sure to do so in your implementations.

ConcurrentWorkers

ConcurrentWorkers is a utility for executing a series of functions concurrently using a pool of workers.

var maxWorkers = 5
var cw = NewConcurrentWorkers(maxWorkers)

for i := 0; i < 10; i++ {
   cw.Execute(func() {
      // do something cool
   })
}

// Stop the workers with an error
cw.Stop(fmt.Errorf("Something went wrong"))

// Stop the workers without an error
cw.Stop(nil)

// Wait for all workers to finish
cw.Wait()
ConcurrentManager

ConcurrentManager is a struct that dynamically manages a pool of workers within set limits. It adjusts worker count based on load, offering functions to allocate, release, and wait for workers, optimizing concurrent task handling.

// NewConcurrentManager creates a new instance of ConcurrentManager with specified parameters.
// It ensures that the provided parameters are within acceptable ranges and initializes the manager.
func NewConcurrentManager(minWorkers, maxWorkers int, workerIncreaseRate float64, timeIncreasePeriod time.Duration) *ConcurrentManager

// Allocate requests a new worker to be allocated.
// It blocks if the maximum number of workers has been reached, until a worker is released.
func (c *ConcurrentManager) Allocate()

// Release frees up a worker, making it available for future tasks.
// It only releases a worker if the release condition is met, ensuring resources are managed efficiently.
func (c *ConcurrentManager) Release()

// Wait blocks until all workers have finished their tasks.
// It ensures that all resources are properly cleaned up before shutting down or reinitializing the manager.
func (c *ConcurrentManager) Wait()
AtomicNumber

AtomicNumber is a utility for managing an number atomically.

// initialize an atomic number with default value 0
var atomic AtomicNumber[int]

atomic.Get() // get the current value
atomic.Set(5) // set the value to 5
atomic.Increment() // increment the value by 1
atomic.IncrementBy(10) // add 10 to the value
atomic.IncrementAndGet() // increment the value by 1 and return the new value
atomic.IncrementByAndGet(10) // add 10 to the value and return the new value
var incremented = atomic.IncrementIf(func(v int) {return v > 0}) // increment the value by 1 if the condition is met
var incrementedBy = atomic.IncrementByIf(10, func(v int) {return v > 0}) // add 10 to the value if the condition is met

// same functions are available for decrementing the value
atomic.Decrement() // decrement the value by 1
...

Load properties from a file with environment variable injections and validations

Utility functions for loading configuration properties from JSON or YAML files. This functionality supports the injection of environment variables directly into the configuration properties.

LoadPropFile supports field validation using struct tags provided by the go-playground/validator library.

You can register your own custom validators using the RegisterCustomValidator function.

devtoolkit provides the following built-in validators:

  • trimmed-non-empty - checks whether a string is not empty after trimming whitespace
dbConfig:
  host: ${DB_HOST}
  port: ${DB_PORT}
  username: ${DB_USERNAME}
  password: ${DB_PASSWORD}
  description: "YAML config file"
{
  "dbConfig": {
    "host": "${DB_HOST}",
    "port": "${DB_PORT}",
    "username": "${DB_USERNAME}",
    "password": "${DB_PASSWORD}",
    "description": "JSON config file"
  }
}
type Config struct {
    DBConfig `json:"dbConfig" yaml:"dbConfig" validate:"required"`
}

type DBConfig struct {
    Host string `json:"host" yaml:"host" validate:"required"`
    Port int `json:"port" yaml:"port" validate:"required,min=1,max=65535"`
    Username string `json:"username" yaml:"username" validate:"required,trimmed-non-empty"`
    Password string `json:"password" yaml:"password" validate:"required,trimmed-non-empty"`
    Description string `json:"description" yaml:"description" validate:"required"`
}

func (p *Config) SetDefaults() {
    p.DBConfig.Host = "localhost"
    p.DBConfig.Port = 3306
}

func trimmedNonEmpty(fl validator.FieldLevel) bool {
    s := fl.Field().String()
    trimmed := strings.TrimSpace(s)
    return len(trimmed) > 0
}

cfg := &Config{}
props := []devtoolkit.ToolKitProp{cfg}
devtoolkit.RegisterCustomValidator("trimmed-non-empty", trimmedNonEmpty)
err := devtoolkit.LoadPropFile("config.json", props)


Resilience

Utility functions and patterns to ensure resilient operation execution.

RetryOperation

The 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.

type ResilienceOptions struct {
    MaxRetries       int                     // indicates the maximum number of retries. Default is 3.
    WaitTime         time.Duration           // indicates the wait time between retries. Default is 100ms.
    Backoff          bool                    // indicates whether to use exponential backoff. Default is false.
    RawError         bool                    // indicates whether to return the raw error or wrap it in a new error. Default is false.
    IsIgnorableErrorHandler func(error) bool // indicates whether to ignore the error or not. Default is nil.
    ReturnIgnorable  bool                    // indicates whether to return the ignorable error or not. Default is false.
}


func NewResilience(options *ResilienceOptions) (Resilience, error)

Example:

operation := func() error {
	return networkCall() // Some hypothetical network operation
}
options := &devtoolkit.ResilienceOptions{
	MaxRetries: 3, 
	WaitTime:   2 * time.Second,
	Backoff:    true,
}

resilienceHandler, err := devtoolkit.NewResilience(options)

if err != nil {
	panic(err)
}

err = resilienceHandler.RetryOperation(operation) // wrapped error returned

if err != nil {
	fmt.Println("Operation failed.", err)
} else {
	fmt.Println("Operation succeeded!")
}

With the RetryOperation function, users can easily add resiliency to their operations and ensure that temporary failures don't lead to complete system failures.


Design Patterns
Process Chain

ProcessChain is an implementation that enables the orderly execution of operations on data within a Go application. Leveraging the "Chain of Responsibility" and "Command" design patterns, it allows for the addition of operations (links) and an optional save step to ensure data integrity after each operation. Ideal for scenarios requiring a series of actions on data with the flexibility to add, remove, or modify steps as needed.

type ProcessChain[T any] interface {
    AddLink(string, LinkFn[T]) error
    SetSaveStep(SaveStep[T])
    GetChain() []string
    Execute(context.Context, T) ([]string, error)
    ExecuteWithIgnorableLinks(context.Context, T, []string) ([]string, error)
}

func NewProcessChain[T any](opts *ProcessChainOptions) ProcessChain[T]

Example:

type Data struct {
    // Your data fields here
}

func step1(d Data) error {
    // Define a process operation
}

func step2(d Data) error {
    // Define a process operation
}

func saveData(d Data) error {
    // Define a save operation
}

chain := NewProcessChain[Data]()
chain.AddLink("step1", step1)
chain.AddLink("step2", step2)
chain.SetSaveStep(saveData)
err := chain.Execute(Data{})

Working with Generic Objects
ToPtr

The ToPtr function takes a value of any type and returns a pointer to it.

val := 5
ptr := devtoolkit.ToPtr(val)
fmt.Println(*ptr) // Returns 5
IsZero

The IsZero function checks whether a value is the zero value of its type.

fmt.Println(devtoolkit.IsZero(0)) // Returns true
fmt.Println(devtoolkit.IsZero(1)) // Returns false
fmt.Println(devtoolkit.IsZero("")) // Returns true
StructToMap

The StructToMap function converts a struct to a map[string]any.

type Person struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Email string `json:"email"`
}

p := Person{
    Name:  "John",
    Age:   30,
    Email: "john@example.com",
}

personMapData, err := devtoolkit.StructToMap(p)
MapToStruct

The MapToStruct function converts a map[string]any to a pointer to a struct.

// personMapData is a map[string]any containing the data of a Person struct, see StructToMap example
ptrToNewPerson, err := devtoolkit.MapToStruct[Person](personMapData)
CastToPointer

CastToPointer casts a value to a pointer of the same type.

func CastToPointer[T any](v any) (*T, bool)

Rules:

  • v must be a pointer.
  • if v not a pointer, returns false.
  • if v is nil, returns false.
  • if v is a pointer but not of the given type, returns false.
  • if v is a pointer of the given type, returns true.
IfThenElse

IfThenElse returns the first value if the condition is true, otherwise it returns the second value.

func IfThenElse[T any](condition bool, first, second T) T
IfThenElseFn

IfThenElseFn returns the first value if the condition is true, otherwise it returns the result of the second value.

func IfThenElseFn[T any](condition bool, first T, second func() T) T
DefaultIfNil

DefaultIfNil returns the first value if it is not nil, otherwise it returns the second value.

func DefaultIfNil[T any](first *T, second T) T
ZeroValue

ZeroValue returns the zero value of a type.

func ZeroValue[T any]() T
ToInt

ToInt converts a value to an int.

func ToInt(value any) (int, bool)
ToFloat64

ToFloat64 converts a value to a float64.

func ToFloat64(value any) (float64, bool)
StrToStruct

StrToStruct converts a string to a struct.

func StrToStruct[T any](s string) (*T, error)

Data structures
Pair

The Pair type represents a pair of values.

type Pair[F any, S any] struct {
    First  F
    Second S
}
Triple

The Triple type represents a triple of values.

type Triple[F any, S any, T any] struct {
    First  F
    Second S
    Third  T
}

Readers
CSV Reader

The CSV reader provides a simple and efficient way to read CSV files in Go.

More details can be found in the CSV Reader documentation.


Generators
struct-guard

The struct-guard tool generates wrapper structs in Go for tracking changes to the fields of the original struct.

More details can be found in the struct-generator documentation.


Working with Slices

Common utility functions for working with slices.

Contains

The Contains function checks whether a slice contains an item. The item must be comparable.

func Contains[T comparable](slice []T, item T) bool

Example:

slice := []int{1, 2, 3}
item := 2
fmt.Println(devtoolkit.Contains(slice, item)) // Returns true
ContainsWithPredicate

The ContainsWithPredicate function checks whether a slice contains an item using a predicate to compare items.

func ContainsWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool

Example:

slice := []int{1, 2, 3}
item := 2
predicate := func(a, b int) bool { return a == b }
fmt.Println(devtoolkit.ContainsWithPredicate(slice, item, predicate)) // Returns true
IndexOf

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.

func IndexOf[T comparable](slice []T, item T) int

Example:

index := IndexOf([]int{1, 2, 3, 2, 1}, 2)
fmt.Println(index) // Output: 1
IndexOfWithPredicate

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.

func IndexOfWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) int

Example:

index := IndexOfWithPredicate([]string{"apple", "banana", "cherry"}, "APPLE", strings.EqualFold)
fmt.Println(index) // Output: 0
LastIndexOf

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.

func LastIndexOf[T comparable](slice []T, item T) int

Example:

index := LastIndexOf([]int{1, 2, 3, 2, 1}, 2)
fmt.Println(index) // Output: 3
LastIndexOfWithPredicate

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.

func LastIndexOfWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) int

Example:

index := LastIndexOfWithPredicate([]string{"apple", "banana", "cherry", "apple"}, "APPLE", strings.EqualFold)
fmt.Println(index) // Output: 3
Remove

Remove removes the first instance of an item from a slice, if present. It returns true if the item was removed, false otherwise.

func Remove[T comparable](slice []T, item T) bool

Example:

removed := Remove([]int{1, 2, 3, 2, 1}, 2)
fmt.Println(removed) // Output: true
RemoveWithPredicate

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.

func RemoveWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool

Example:

removed := RemoveWithPredicate([]string{"apple", "banana", "cherry"}, "APPLE", strings.EqualFold)
fmt.Println(removed) // Output: true
RemoveAll

RemoveAll removes all instances of an item from a slice, if present. It returns true if the item was removed, false otherwise.

func RemoveAll[T comparable](slice []T, item T) bool

Example:

removed := RemoveAll([]int{1, 2, 3, 2, 1}, 2)
fmt.Println(removed) // Output: true
RemoveAllWithPredicate

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.

func RemoveAllWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool

Example:

removed := RemoveAllWithPredicate([]string{"apple", "banana", "cherry", "apple"}, "APPLE", strings.EqualFold)
fmt.Println(removed) // Output: true
RemoveAt

RemoveAt removes the item at a given index from a slice. It returns true if the item was removed, false otherwise.

func RemoveAt[T any](slice []T, index int) bool

Example:

removed := RemoveAt([]int{1, 2, 3}, 1)
fmt.Println(removed) // Output: true
RemoveRange

RemoveRange removes the items in a given range from a slice. It returns true if items were removed, false otherwise.

func RemoveRange[T any](slice []T, start, end int) bool

Example:

removed := RemoveRange([]int{1, 2, 3, 4, 5}, 1, 3)
fmt.Println(removed) // Output: true
RemoveIf

RemoveIf removes all items from a slice for which a predicate function returns true. It returns true if any items were removed, false otherwise.

func RemoveIf[T any](slice []T, predicate func(T) bool) bool

Example:

removed := RemoveIf([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })
fmt.Println(removed) // Output: true
Filter

Filter returns a new slice containing all items from the original slice for which a predicate function returns true.

func Filter[T any](slice []T, predicate func(T) bool) []T

Example:

filtered := Filter([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })
fmt.Println(filtered) // Output: [2 4]
FilterNot

FilterNot returns a new slice containing all items from the original slice for which a predicate function returns false.

func FilterNot[T any](slice []T, predicate func(T) bool) []T

Example:

filtered := FilterNot([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })
fmt.Println(filtered) // Output: [1 3 5]
Map

Map applies a transformation function to all items in a slice and returns a new slice containing the results.

func Map[T, R any](slice []T, mapper func(T) R) []R 

Example:

mapped := Map([]int{1, 2, 3}, func(n int) int { return n * 2 })
fmt.Println(mapped) // Output: [2 4 6]
RemoveDuplicates

RemoveDuplicates removes all duplicate items from a slice. It returns true if any items were removed, false otherwise.

func RemoveDuplicates[T comparable](slice []T) bool

Example:

removed := RemoveDuplicates([]int{1, 2, 3, 2, 1})
fmt.Println(removed) // Output: true
Reverse

Reverse reverses the order of items in a slice.

func Reverse[T any](slice []T)

Example:

data := []int{1, 2, 3}
Reverse(data)
fmt.Println(data) // Output: [3 2 1]
Difference

Difference returns a new slice containing all items from the original slice that are not present in the other slice.

func Difference[T comparable](slice, other []T) []T

Example:

diff := Difference([]int{1, 2, 3, 4, 5}, []int{3, 4, 5, 6, 7})
fmt.Println(diff) // Output: [1 2]
Intersection

Intersection returns a new slice containing all items from the original slice that are also present in the other slice.

func Intersection[T comparable](slice, other []T) []T

Example:

inter := Intersection([]int{1, 2, 3, 4, 5}, []int{3, 4, 5, 6, 7})
fmt.Println(inter) // Output: [3 4 5]
Union

Union returns a new slice containing all unique items from both the original slice and the other slice.

func Union[T comparable](slice, other []T) []T

Example:

union := Union([]int{1, 2, 3}, []int{3, 4, 5})
fmt.Println(union) // Output: [1 2 3 4 5]
GetMapKeys

GetMapKeys returns a slice of keys from a map.

func GetMapKeys[K comparable, V any](m map[K]V) []K

Example:

keys := GetMapKeys(map[string]int{"a": 1, "b": 2})
fmt.Println(keys) // Output: [a b]
GetMapValues

GetMapValues returns a slice of values from a map.

func GetMapValues[K comparable, V any](m map[K]V, removeDuplicates bool) []V

Example:

values := GetMapValues(map[string]int{"a": 1, "b": 2, "c": 1}, false)
fmt.Println(values) // Output: [1 2 1]

values = GetMapValues(map[string]int{"a": 1, "b": 2, "c": 1}, true)
fmt.Println(values) // Output: [1 2]

Contributions

Contributions 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.

License

Devtoolkit is licensed under the MIT License. Please see the LICENSE file for details.

Documentation

Overview

Package devtoolkit provides a collection of utilities for Golang development.

Index

Constants

This section is empty.

Variables

View Source
var (
	ConcurrentExecAlreadyRunningErr = errors.New("concurrent fns already running")
	ConcurrentExecNilContextErr     = errors.New("context must not be nil")
	ConcurrentExecFnsNilOrEmptyErr  = errors.New("fns must not be nil or empty")
)

Error values that can be returned by ConcurrentExec.

View Source
var (
	ErrNilLinkFn = errors.New("nil link function")
)

Functions

func CastToPointer added in v1.4.0

func CastToPointer[T any](v any) (*T, bool)

CastToPointer casts the given value to a pointer of the given type. v must be a pointer. if v not a pointer, returns false. if v is nil, returns false. if v is a pointer but not of the given type, returns false. if v is a pointer of the given type, returns true.

func Contains

func Contains[T comparable](slice []T, item T) bool

Contains checks if a slice contains an item. Item must be comparable.

func ContainsWithPredicate

func ContainsWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool

ContainsWithPredicate checks if a slice contains an item. Use predicate to compare items.

func DefaultIfNil added in v1.4.0

func DefaultIfNil[T any](a *T, b T) T

DefaultIfNil returns 'a' if 'a' is not nil, otherwise returns 'b'.

func Difference

func Difference[T comparable](slice, other []T) []T

Difference returns a new slice containing all items from slice that are not present in other.

func Filter

func Filter[T any](slice []T, predicate func(T) bool) []T

Filter returns a new slice containing all items from slice for which predicate returns true.

func FilterNot

func FilterNot[T any](slice []T, predicate func(T) bool) []T

FilterNot returns a new slice containing all items from slice for which predicate returns false.

func GetMapKeys added in v1.4.0

func GetMapKeys[K comparable, V any](m map[K]V) []K

GetMapKeys returns a new slice containing all keys from the given map.

func GetMapValues added in v1.4.0

func GetMapValues[K comparable, V comparable](m map[K]V, removeDuplicates bool) []V

GetMapValues returns a new slice containing all values from the given map. Note that the order of values is not guaranteed

func IfThenElse added in v1.4.0

func IfThenElse[T any](condition bool, a, b T) T

IfThenElse returns 'a' if condition is true, otherwise returns 'b'.

func IfThenElseFn added in v1.4.0

func IfThenElseFn[T any](condition bool, a, b func() T) T

IfThenElseFn returns 'a' if condition is true, otherwise returns 'b'.

func IndexOf

func IndexOf[T comparable](slice []T, item T) int

IndexOf returns the index of the first instance of item in slice, or -1 if item is not present in slice.

func IndexOfWithPredicate

func IndexOfWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) int

IndexOfWithPredicate returns the index of the first instance of item in slice, or -1 if item is not present in slice. Use predicate to compare items.

func Intersection

func Intersection[T comparable](slice, other []T) []T

Intersection returns a new slice containing all items from slice that are also present in other.

func IsZero

func IsZero(t any) bool

IsZero returns true if the given value is the zero value for its type.

func LastIndexOf

func LastIndexOf[T comparable](slice []T, item T) int

LastIndexOf returns the index of the last instance of item in slice, or -1 if item is not present in slice.

func LastIndexOfWithPredicate

func LastIndexOfWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) int

LastIndexOfWithPredicate returns the index of the last instance of item in slice, or -1 if item is not present in slice. Use predicate to compare items.

func LoadPropFile

func LoadPropFile(filePath string, props []ToolKitProp) error

LoadPropFile loads configuration properties from a file into the provided slice of structs. The file format can be either YAML or JSON. The 'filePath' parameter specifies the path to the configuration file. The 'props' parameter is a slice of pointers to struct instances that should be populated with the loaded properties. Returns an error if the file cannot be loaded, parsed, or is of an unsupported format.

func Map

func Map[T, R any](slice []T, mapper func(T) R) []R

Map returns a new slice containing the results of applying the given mapper function to each item in slice.

func MapToStruct added in v1.4.0

func MapToStruct[T any](m map[string]any) (*T, error)

MapToStruct converts a map[string]any to a struct.

func RegisterCustomValidator added in v1.2.0

func RegisterCustomValidator(name string, fn func(fl validator.FieldLevel) bool)

RegisterCustomValidator registers a custom validator function with the validator.

func Remove

func Remove[T comparable](slice []T, item T) bool

Remove removes the first instance of item from slice, if present. Returns true if item was removed, false otherwise.

func RemoveAll

func RemoveAll[T comparable](slice []T, item T) bool

RemoveAll removes all instances of item from slice, if present. Returns true if item was removed, false otherwise.

func RemoveAllWithPredicate

func RemoveAllWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool

RemoveAllWithPredicate removes all instances of item from slice, if present. Use predicate to compare items. Returns true if item was removed, false otherwise.

func RemoveAt

func RemoveAt[T any](slice []T, index int) bool

RemoveAt removes the item at the given index from slice. Returns true if item was removed, false otherwise.

func RemoveDuplicates

func RemoveDuplicates[T comparable](slice []T) bool

RemoveDuplicates removes all duplicate items from slice. Returns true if items were removed, false otherwise.

func RemoveIf

func RemoveIf[T any](slice []T, predicate func(T) bool) bool

RemoveIf removes all items from slice for which predicate returns true. Returns true if items were removed, false otherwise.

func RemoveRange

func RemoveRange[T any](slice []T, start, end int) bool

RemoveRange removes the items in the given range from slice. Returns true if items were removed, false otherwise.

func RemoveWithPredicate

func RemoveWithPredicate[T any](slice []T, item T, predicate func(T, T) bool) bool

RemoveWithPredicate removes the first instance of item from slice, if present. Use predicate to compare items. Returns true if item was removed, false otherwise.

func Reverse

func Reverse[T any](slice []T)

Reverse reverses the order of items in slice.

func StrToStruct added in v1.4.0

func StrToStruct[T any](s string) (*T, error)

StrToStruct converts a string to a struct.

func StructToMap added in v1.4.0

func StructToMap(t any) (map[string]any, error)

StructToMap converts a struct to a map[string]any.

func ToFloat64 added in v1.4.0

func ToFloat64(value any) (float64, bool)

ToFloat64 converts the given value to float64.

func ToInt added in v1.4.0

func ToInt(value any) (int, bool)

ToInt converts the given value to int. Converts float64, float32, int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8 to int.

func ToPtr

func ToPtr[T any](t T) *T

ToPtr returns a pointer to the given value.

func Union

func Union[T comparable](slice, other []T) []T

Union returns a new slice containing all items from slice and other.

func ZeroValue added in v1.4.0

func ZeroValue[T any]() T

ZeroValue returns the zero value of the given type.

Types

type AtomicNumber added in v1.4.0

type AtomicNumber[T Number] struct {
	// contains filtered or unexported fields
}

AtomicNumber provides a concurrency-safe way to work with numeric values.

func (*AtomicNumber[T]) Decrement added in v1.4.0

func (a *AtomicNumber[T]) Decrement()

Decrement decreases the AtomicNumber's value by 1.

func (*AtomicNumber[T]) DecrementAndGet added in v1.4.0

func (a *AtomicNumber[T]) DecrementAndGet() T

DecrementAndGet decreases the AtomicNumber's value by 1 and returns the new value.

func (*AtomicNumber[T]) DecrementBy added in v1.4.0

func (a *AtomicNumber[T]) DecrementBy(n T)

DecrementBy decreases the AtomicNumber's value by the provided amount.

func (*AtomicNumber[T]) DecrementByAndGet added in v1.4.0

func (a *AtomicNumber[T]) DecrementByAndGet(n T) T

DecrementByAndGet decreases the AtomicNumber's value by the provided amount and returns the new value.

func (*AtomicNumber[T]) DecrementByIf added in v1.4.0

func (a *AtomicNumber[T]) DecrementByIf(n T, cond func(T) bool) bool

DecrementByIf decreases the AtomicNumber's value by the provided amount if the provided condition is true. It returns true if the value was decremented.

func (*AtomicNumber[T]) DecrementIf added in v1.4.0

func (a *AtomicNumber[T]) DecrementIf(cond func(T) bool) bool

DecrementIf decreases the AtomicNumber's value by 1 if the provided condition is true. It returns true if the value was decremented.

func (*AtomicNumber[T]) EqualTo added in v1.4.0

func (a *AtomicNumber[T]) EqualTo(value T) bool

EqualTo returns true if the AtomicNumber's value is equal to the provided value.

func (*AtomicNumber[T]) Get added in v1.4.0

func (a *AtomicNumber[T]) Get() T

Get returns the current value of the AtomicNumber.

func (*AtomicNumber[T]) GreaterThan added in v1.4.0

func (a *AtomicNumber[T]) GreaterThan(value T) bool

GreaterThan returns true if the AtomicNumber's value is greater than the provided value.

func (*AtomicNumber[T]) Increment added in v1.4.0

func (a *AtomicNumber[T]) Increment()

Increment increases the AtomicNumber's value by 1.

func (*AtomicNumber[T]) IncrementAndGet added in v1.4.0

func (a *AtomicNumber[T]) IncrementAndGet() T

IncrementAndGet increases the AtomicNumber's value by 1 and returns the new value.

func (*AtomicNumber[T]) IncrementBy added in v1.4.0

func (a *AtomicNumber[T]) IncrementBy(n T)

IncrementBy increases the AtomicNumber's value by the provided amount.

func (*AtomicNumber[T]) IncrementByAndGet added in v1.4.0

func (a *AtomicNumber[T]) IncrementByAndGet(n T) T

IncrementByAndGet increases the AtomicNumber's value by the provided amount and returns the new value.

func (*AtomicNumber[T]) IncrementByIf added in v1.4.0

func (a *AtomicNumber[T]) IncrementByIf(n T, cond func(T) bool) bool

IncrementByIf increases the AtomicNumber's value by the provided amount if the provided condition is true. It returns true if the value was incremented.

func (*AtomicNumber[T]) IncrementIf added in v1.4.0

func (a *AtomicNumber[T]) IncrementIf(cond func(T) bool) bool

IncrementIf increases the AtomicNumber's value by 1 if the provided condition is true. It returns true if the value was incremented.

func (*AtomicNumber[T]) LessThan added in v1.4.0

func (a *AtomicNumber[T]) LessThan(value T) bool

LessThan returns true if the AtomicNumber's value is less than the provided value.

func (*AtomicNumber[T]) Set added in v1.4.0

func (a *AtomicNumber[T]) Set(value T)

Set updates the value of the AtomicNumber.

type ConcurrentExec

type ConcurrentExec struct {
	// contains filtered or unexported fields
}

ConcurrentExec allows to execute a slice of ConcurrentFn concurrently. The running state, results, errors and context for the concurrent execution are stored within the struct.

func NewConcurrentExec added in v1.1.1

func NewConcurrentExec() *ConcurrentExec

func (*ConcurrentExec) CancelExecution

func (ce *ConcurrentExec) CancelExecution()

func (*ConcurrentExec) Done

func (ce *ConcurrentExec) Done() <-chan struct{}

func (*ConcurrentExec) Errors

func (ce *ConcurrentExec) Errors() []error

func (*ConcurrentExec) ExecuteFns

func (ce *ConcurrentExec) ExecuteFns(ctx context.Context, fns ...ConcurrentFn) (ConcurrentExecResponse, error)

ExecuteFns receives a context and a slice of functions to execute concurrently. It returns a ConcurrentExecResponse interface and an error if execution could not be started.

func (*ConcurrentExec) GetNotNilErrors added in v1.4.0

func (ce *ConcurrentExec) GetNotNilErrors() []error

func (*ConcurrentExec) Results

func (ce *ConcurrentExec) Results() []any

type ConcurrentExecResponse

type ConcurrentExecResponse interface {
	// Results blocks until all functions are done and returns the results.
	Results() []any // blocks until all fns are done

	// Errors blocks until all functions are done and returns any errors that occurred.
	Errors() []error // blocks until all fns are done

	// GetNotNilErrors blocks until all functions are done and returns any errors that occurred that are not nil.
	GetNotNilErrors() []error // blocks until all fns are done

	// CancelExecution cancels the execution of all functions.
	CancelExecution() // cancels the execution of all fns

	// Done returns a channel that is closed when all functions are done.
	Done() <-chan struct{} // returns a channel that is closed when all fns are done
}

ConcurrentExecResponse is the interface returned by ExecuteFns to interact with the results of the concurrent execution.

type ConcurrentFn

type ConcurrentFn func(ctx context.Context) (any, error)

ConcurrentFn represents a function that can be executed concurrently. The function receives a context and returns a result and an error.

type ConcurrentManager added in v1.4.0

type ConcurrentManager struct {
	// contains filtered or unexported fields
}

ConcurrentManager is a structure that manages a dynamic pool of workers. It can adjust the number of active workers based on the workload, within the provided minimum and maximum limits.

func NewConcurrentManager added in v1.4.0

func NewConcurrentManager(minWorkers, maxWorkers int, workerIncreaseRate float64, timeIncreasePeriod time.Duration) *ConcurrentManager

NewConcurrentManager creates a new instance of ConcurrentManager with specified parameters. It ensures that the provided parameters are within acceptable ranges and initializes the manager.

func (*ConcurrentManager) Allocate added in v1.4.0

func (c *ConcurrentManager) Allocate()

Allocate requests a new worker to be allocated. It blocks if the maximum number of workers has been reached, until a worker is released.

func (*ConcurrentManager) Release added in v1.4.0

func (c *ConcurrentManager) Release()

Release frees up a worker, making it available for future tasks. It only releases a worker if the release condition is met, ensuring resources are managed efficiently.

func (*ConcurrentManager) Wait added in v1.4.0

func (c *ConcurrentManager) Wait()

Wait blocks until all workers have finished their tasks. It ensures that all resources are properly cleaned up before shutting down or reinitializing the manager.

type ConcurrentWorkers added in v1.4.0

type ConcurrentWorkers struct {
	// contains filtered or unexported fields
}

func NewConcurrentWorkers added in v1.4.0

func NewConcurrentWorkers(maxWorkers int) *ConcurrentWorkers

func (*ConcurrentWorkers) Execute added in v1.4.0

func (cw *ConcurrentWorkers) Execute(fn func())

func (*ConcurrentWorkers) GetError added in v1.4.0

func (cw *ConcurrentWorkers) GetError() error

func (*ConcurrentWorkers) IsOpen added in v1.4.0

func (cw *ConcurrentWorkers) IsOpen() bool

func (*ConcurrentWorkers) Stop added in v1.4.0

func (cw *ConcurrentWorkers) Stop(err error)

func (*ConcurrentWorkers) Wait added in v1.4.0

func (cw *ConcurrentWorkers) Wait()

type LinkFn added in v1.4.0

type LinkFn[T any] func(context.Context, T) error

type Number added in v1.4.0

type Number interface {
	constraints.Integer | constraints.Float
}

Number is a type constraint that allows any type which is either an Integer or a Float.

type Pair added in v1.4.0

type Pair[F any, S any] struct {
	First  F
	Second S
}

Pair is a generic pair of values

func NewPair added in v1.4.0

func NewPair[F any, S any](first F, second S) Pair[F, S]

func (*Pair[F, S]) GetAll added in v1.4.0

func (p *Pair[F, S]) GetAll() (F, S)

func (*Pair[F, S]) GetFirst added in v1.4.0

func (p *Pair[F, S]) GetFirst() F

func (*Pair[F, S]) GetSecond added in v1.4.0

func (p *Pair[F, S]) GetSecond() S

type ProcessChain added in v1.4.0

type ProcessChain[T any] interface {
	// AddLink adds a new link, identified by a string key, to the chain of operations.
	// It returns an error if the provided link function is nil.
	AddLink(string, LinkFn[T]) error

	// SetSaveStep sets a save step function that is executed after each link in the chain.
	// This step is used to persist the state of the data after each operation.
	SetSaveStep(SaveStep[T])

	// GetChain returns a slice of string keys representing the sequence of links added to the chain.
	GetChain() []string

	// Execute runs the process chain on data of type T, sequentially executing
	// each link in the order they were added.
	// It returns a slice of string keys representing the successfully executed links and an error if the execution
	// of any link fails.
	Execute(context.Context, T) ([]string, error)

	// ExecuteWithIgnorableLinks runs the process chain on data of type T, sequentially executing
	// each link in the order they were added, except for the ignorable links.
	// It returns a slice of string keys representing the successfully executed links and an error if the execution
	// of any link fails.
	ExecuteWithIgnorableLinks(context.Context, T, []string) ([]string, error)
}

ProcessChain defines an interface for a chain of operations (links) that can be executed on data of type T. It allows adding links, setting a save step, executing the chain, and retrieving the sequence of added links.

func NewProcessChain added in v1.4.0

func NewProcessChain[T any](opts *ProcessChainOptions) ProcessChain[T]

NewProcessChain creates and returns a new instance of a process chain for data of type T.

type ProcessChainOptions added in v1.4.0

type ProcessChainOptions struct {
	AddLinkNameToError bool // default: false
}

type Resilience added in v1.1.0

type Resilience interface {
	RetryOperation(operation func() error) error
}

Resilience provides an interface for retrying operations in case of failure.

func NewResilience added in v1.1.0

func NewResilience(options *ResilienceOptions) (Resilience, error)

NewResilience returns a new Resilience instance with the provided options or defaults.

type ResilienceOptions added in v1.1.0

type ResilienceOptions struct {
	MaxRetries              int              // indicates the maximum number of retries. Default is 3.
	WaitTime                time.Duration    // indicates the wait time between retries. Default is 100ms.
	Backoff                 bool             // indicates whether to use exponential backoff. Default is false.
	RawError                bool             // indicates whether to return the raw error or wrap it in a new error. Default is false.
	IsIgnorableErrorHandler func(error) bool // indicates whether to ignore the error or not. Default is nil.
	ReturnIgnorable         bool             // indicates whether to return the ignorable error or not. Default is false.
}

ResilienceOptions contains configuration parameters for retry operations.

type SaveStep added in v1.4.0

type SaveStep[T any] func(context.Context, T, []string) error

type ToolKitProp added in v1.3.0

type ToolKitProp interface {
	SetDefaults()
}

ToolKitProp is an interface that must be implemented by all configuration property structs. It provides a method to set default values for the properties.

type Triple added in v1.4.0

type Triple[F any, S any, T any] struct {
	First  F
	Second S
	Third  T
}

Triple is a generic triple of values

func NewTriple added in v1.4.0

func NewTriple[F any, S any, T any](first F, second S, third T) Triple[F, S, T]

func (Triple[F, S, T]) GetAll added in v1.4.0

func (t Triple[F, S, T]) GetAll() (F, S, T)

func (Triple[F, S, T]) GetFirst added in v1.4.0

func (t Triple[F, S, T]) GetFirst() F

func (Triple[F, S, T]) GetSecond added in v1.4.0

func (t Triple[F, S, T]) GetSecond() S

func (Triple[F, S, T]) GetThird added in v1.4.0

func (t Triple[F, S, T]) GetThird() T

Directories

Path Synopsis
generator
struct-guard command
reader
csv

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL