tricks

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2025 License: GPL-3.0 Imports: 5 Imported by: 6

README

Tricks Coverage Badge

Frequent magics every developer may need

Usage

go get github.com/janstoon/toolbox/tricks

Documentation

Index

Examples

Constants

View Source
const IndexUnavailable = -1

IndexUnavailable is used in methods which are ought to return index of something, but they failed finding it and want to express that it's unavailable,

Variables

View Source
var ErrDuplicateEntry = errors.New("duplicate entry")

Functions

func All added in v1.0.0

func All[E any](seq iter.Seq[E], matcher Matcher[E]) bool

All returns true if all elements in the seq satisfy the predicate using matcher. If seq is empty, it returns true.

func Any added in v1.0.0

func Any[E any](seq iter.Seq[E], matcher Matcher[E]) bool

Any returns true if any element in the seq satisfies the predicate using matcher. If the seq is empty, it returns false. It's equivalent to slices.ContainsFunc

func ApplyOptions

func ApplyOptions[S any](s *S, oo ...Option[S]) *S

ApplyOptions performs modifications of all Option(s) on S sequentially.

Example
package main

import (
	"fmt"

	"github.com/janstoon/toolbox/tricks"
)

func main() {
	type configuration struct {
		scope         string
		verbose       bool
		skipSignature bool
		maxRetries    int
	}

	options := make([]tricks.Option[configuration], 0)
	options = append(options, tricks.ImmutableOption[configuration](func(s configuration) configuration {
		s.scope = "example"

		return s
	}))

	options = append(options, tricks.MutableOption[configuration](func(s *configuration) {
		s.verbose = true
	}))

	options = append(options, tricks.ImmutableOption[configuration](func(s configuration) configuration {
		s.maxRetries = 5

		return s
	}))

	cfg := new(configuration)
	cfg = tricks.ApplyOptions(cfg, options...)

	fmt.Println(cfg)
}
Output:

&{example true false 5}

func Chain added in v1.0.0

func Chain[E any](ss ...iter.Seq[E]) iter.Seq[E]

Chain returns a new seq that chains multiple sequences.

func Coalesce

func Coalesce[T comparable](tt ...T) T

Coalesce returns left-most non-zero value It's like cmp.Or

func Count added in v1.0.0

func Count[E any](seq iter.Seq[E]) int

Count returns the number of elements in the seq.

func Distinct added in v1.0.0

func Distinct[E comparable](seq iter.Seq[E]) iter.Seq[E]

Distinct returns a new seq with distinct elements.

func DistinctBy added in v1.0.0

func DistinctBy[E any, K comparable](seq iter.Seq[E], transformer Transformer[E, K]) iter.Seq[E]

DistinctBy returns a new seq with distinct elements. Transformer is used to determine the key of the element to check elements' equality.

func ElementAt added in v1.0.0

func ElementAt[E any](seq iter.Seq[E], index int) (E, bool)

ElementAt returns the element at the specified index. If the index is out of range, it returns the zero value of E and false.

func ElementAtOrDefault added in v1.0.0

func ElementAtOrDefault[E any](seq iter.Seq[E], index int, defaultValue E) E

ElementAtOrDefault returns the element at the specified index. If the index is out of range, it returns the default value.

func ElementAtOrElse added in v1.0.0

func ElementAtOrElse[E any](seq iter.Seq[E], index int, defaultFunc func() E) E

ElementAtOrElse returns the element at the specified index. If the index is out of range, it returns the value from the defaultFunc.

func Extend added in v1.0.0

func Extend[Slice ~[]E, E any](seq iter.Seq[E], s Slice) iter.Seq[E]

Extend returns a new seq that chains a seq with a slice.

func Filter

func Filter[E any](seq iter.Seq[E], matcher Matcher[E]) iter.Seq[E]

Filter returns a new iterator with elements that satisfy the predicate. The order of the elements is preserved. If no element satisfies the predicate, it returns an empty iterator.

func Find

func Find[E any](seq iter.Seq[E], matcher Matcher[E]) (E, bool)

Find returns the first element in seq that satisfies the predicate using matcher. If no element was found, it returns nil.

func First added in v1.0.0

func First[E any](seq iter.Seq[E]) (E, bool)

First returns the first element in the iterator. If the iterator is empty, it returns the zero value of T and false.

func Flat added in v0.6.3

func Flat[E any](ss ...iter.Seq[E]) iter.Seq[E]

Flat merges multiple sequences of same type into one sequence. It does not modify nor drop elements. So output may contain elements with duplicate values from different sequences. It's an alternative to slices.Concat.

func FlatMap added in v1.0.0

func FlatMap[S, D any](seq iter.Seq[S], transformer Transformer[S, iter.Seq[D]]) iter.Seq[D]

FlatMap returns a new seq with elements that are transformed by the transformer and flattened into new sequence.

func ForEach added in v1.0.0

func ForEach[E any](seq iter.Seq[E], f func(E))

ForEach calls the function for each element in the seq.

func FromAny added in v0.8.1

func FromAny[T any](src any) T

FromAny tries to cast any to type T. If cast failed it returns zero value of type T. One use-case is to feed a method which accepts []T, but you have []ant in hand.

func Identity added in v1.1.0

func Identity[T any](t T) T

Identity is a transformer which returns input without any modification. It's also the simplest Middleware which directly returns the next handler aka passthrough middleware.

func Index added in v1.0.0

func Index[K, V any](seq iter.Seq2[K, V], matcher Matcher[V]) (K, bool)

Index returns the index of the first element that satisfies the predicate using matcher and true. If no element was found, it returns zero value of K and false.

func IndexOf

func IndexOf[K any, V comparable](seq iter.Seq2[K, V], expected V) (K, bool)

IndexOf returns the index of the element and true. If no element was found, it returns zero value of K and false.

func InsertIfNotExist

func InsertIfNotExist[K comparable, V any](hm map[K]V, key K, value V)

InsertIfNotExist puts value in hm[key] if hm[key] is not already full. If it's already filled it panics with ErrDuplicateEntry

func Last added in v1.0.0

func Last[E any](seq iter.Seq[E]) (E, bool)

Last returns the last element in the iterator. If the iterator is empty, it returns the zero value of T and false.

func LastIndex added in v1.0.0

func LastIndex[K, V any](seq iter.Seq2[K, V], matcher Matcher[V]) (K, bool)

LastIndex returns the index of the last element that satisfies the predicate using matcher and true. If no element was found, it returns zero value of K and false.

func LastIndexOf added in v1.0.0

func LastIndexOf[K any, V comparable](seq iter.Seq2[K, V], expected V) (K, bool)

LastIndexOf returns the last index of the element and true. If no element was found, it returns zero value of K and false.

func Map

func Map[S, D any](seq iter.Seq[S], transformer Transformer[S, D]) iter.Seq[D]

Map returns a new seq with elements that are transformed by the transformer. Input and output sequences have same length.

func PtrPtr

func PtrPtr[S, D any](src *S, transformer Transformer[S, D]) *D

PtrPtr transforms pointer of type S to pointer of type D using Transformer. If src is nil output is nil too. It's a safe transformation with nil guard and safe pointer dereference.

func PtrVal

func PtrVal[T any](src *T) T

PtrVal dereferences a pointer of type T. If it's nil it returns the zero value of T. It's a safe pointer dereference method intended for use cases where a value is required, even if the pointer is nil or empty.

func Reduce

func Reduce[E, A any](seq iter.Seq[E], reducer Reducer[A, E], initial A) A

Reduce reduces the seq to a single value using reducer to combine the elements. It performs reducer on all elements sequentially from first to last and returns output of last reducer call. Reducer accumulator is set to initial for first call. If the seq is empty, it returns initial value.

func Skip added in v1.0.0

func Skip[E any](seq iter.Seq[E], n int) iter.Seq[E]

Skip returns a new seq with the first n elements skipped.

func SkipWhile added in v1.0.0

func SkipWhile[E any](seq iter.Seq[E], matcher Matcher[E]) iter.Seq[E]

SkipWhile returns a new seq with elements skipped while the predicate is true.

func SliceAll added in v1.0.0

func SliceAll[Slice ~[]E, E any](s Slice, matcher Matcher[E]) bool

SliceAll performs All on slice

func SliceAny added in v1.0.0

func SliceAny[Slice ~[]E, E any](s Slice, matcher Matcher[E]) bool

SliceAny performs Any on slice

func SliceClone added in v1.0.0

func SliceClone[Slice ~[]E, E any](s Slice) Slice

SliceClone creates a copy of slice(s) which can be modified independently without any effect on original slice. It's equivalent to slices.Clone

func SliceDistinct added in v1.0.0

func SliceDistinct[Slice ~[]E, E comparable](s Slice) Slice

SliceDistinct performs Distinct on slice

func SliceDistinctBy added in v1.0.0

func SliceDistinctBy[Slice ~[]E, E any, K comparable](s Slice, transformer Transformer[E, K]) Slice

SliceDistinctBy performs DistinctBy on slice

func SliceFilter added in v1.0.0

func SliceFilter[Slice ~[]E, E any](s Slice, matcher Matcher[E]) Slice

SliceFilter returns a new slice consisting of original slice elements which matched using matcher. It returns nil if no element was matched.

func SliceFind added in v1.0.0

func SliceFind[Slice ~[]E, E any](s Slice, matcher Matcher[E]) (E, bool)

SliceFind performs Find on slice

func SliceFlat added in v1.0.0

func SliceFlat[Slice ~[]E, E any](ss ...Slice) Slice

SliceFlat merges multiple slices of same type(Slice) into one slice. It does not modify nor drop elements. So output may contain elements with duplicate values from different slices. It's an alternative to slices.Concat.

func SliceFlatMap added in v1.0.0

func SliceFlatMap[SS ~[]S, DD ~[]D, S, D any](ss SS, transformer Transformer[S, DD]) DD

func SliceIndex added in v1.0.0

func SliceIndex[Slice ~[]E, E any](s Slice, matcher Matcher[E]) int

SliceIndex performs Index on slice. It returns IndexUnavailable if no element was found. It's Equivalent to slices.IndexFunc.

func SliceIndexOf added in v1.0.0

func SliceIndexOf[Slice ~[]E, E comparable](expected E, s Slice) int

SliceIndexOf searches slice for first element which is equal to expected and returns index of it or IndexUnavailable if not found.

func SliceLastIndex added in v1.0.0

func SliceLastIndex[Slice ~[]E, E any](s Slice, matcher Matcher[E]) int

SliceLastIndex performs LastIndex on slice. It returns IndexUnavailable if no element was found. It's Equivalent to slices.IndexFunc.

func SliceLastIndexOf added in v1.0.0

func SliceLastIndexOf[Slice ~[]E, E comparable](expected E, s Slice) int

SliceLastIndexOf searches slice for last element which is equal to expected and returns index of it or IndexUnavailable if not found.

func SliceMap added in v1.0.0

func SliceMap[SS ~[]S, DD ~[]D, S, D any](ss SS, transformer Transformer[S, D]) DD

SliceMap iterates over ss, applies transformer on each individual element of it and returns the transformed slice. Input and output slices have same length.

func SliceReduce added in v1.0.0

func SliceReduce[Slice ~[]E, E, A any](s Slice, reducer Reducer[A, E], initial A) A

SliceReduce takes slice s, performs reducer on all elements sequentially from start to end and returns output of last reducer call. Reducer accumulator is set to initial for first call. If the seq is empty, it returns initial value.

func StringToRunes

func StringToRunes(src string) []rune

StringToRunes casts string into slice of underlying rune(s)

func Take added in v1.0.0

func Take[E any](seq iter.Seq[E], n int) iter.Seq[E]

Take returns a new seq with the first n elements taken.

func TakeWhile added in v1.0.0

func TakeWhile[E any](seq iter.Seq[E], matcher Matcher[E]) iter.Seq[E]

TakeWhile returns a new seq with elements taken while the predicate is true.

func ToAny added in v0.8.1

func ToAny[T any](src T) any

ToAny casts type T to any. One use-case is to feed a method which accepts []any, but you have []T in hand.

func ValPtr

func ValPtr[T any](src T) *T

ValPtr converts a value of type T to its pointer. It simply returns address of src and is optimal if inlined by the compiler. Since input is passed by value it returns a pointer to the copied variable and further modifications on it does not change value of the input variable. This method is intended for use cases where expected type is a pointer for reasons other than modification like protobuf data structures, api dto or storage dao.

Types

type ImmutableOption added in v1.1.0

type ImmutableOption[S any] func(s S) S

ImmutableOption takes a copy of S and returns the modified copy of it.

func (ImmutableOption[S]) Apply added in v1.1.0

func (o ImmutableOption[S]) Apply(s *S) *S

type Matcher added in v1.0.0

type Matcher[T any] interface {
	// Match should return true if actual meets the criteria and false if it doesn't.
	Match(actual T) bool
}

Matcher performs matching against value of type T. It's usable in filtering, searching and checking tasks which need a predicator to check each individual element.

func MatchEmptyString added in v1.1.0

func MatchEmptyString() Matcher[string]

MatchEmptyString matches actual if it's empty string ignoring whitespaces

func MatchEqual

func MatchEqual[T comparable](expected T) Matcher[T]

MatchEqual matches actual if it's equal to expected actual == expected

func MatchGreaterThan added in v1.0.0

func MatchGreaterThan[T cmp.Ordered](expected T) Matcher[T]

MatchGreaterThan matches actual if it's greater than expected actual > expected

func MatchLesserThan added in v1.0.0

func MatchLesserThan[T cmp.Ordered](expected T) Matcher[T]

MatchLesserThan matches actual if it's lesser than expected actual < expected

type MatcherFunc added in v1.0.0

type MatcherFunc[T any] func(actual T) bool

MatcherFunc creates a Matcher from a function which takes value of type T and tells if it meets the criteria or not.

func (MatcherFunc[T]) Match added in v1.0.0

func (f MatcherFunc[T]) Match(actual T) bool

type Middleware added in v0.9.0

type Middleware[H any] func(next H) H

Middleware is simply a function that generates H which ought to be a handler. It's a wrapper that takes the next H as input and decides to call it or not in the generated H anywhere desired. H can be http.Handler, grpc.UnaryServerInterceptor, queue message handler or any other task handler. Simplest Middleware is Identity which directly returns the next H as the generated H aka passthrough middleware.

type MiddlewareStack added in v0.9.0

type MiddlewareStack[H any] Middleware[H]

MiddlewareStack is a mechanism to chain multiple Middleware(s) and output a single entrypoint. Middleware(s) should all accept and generate same handler type. Think of it as http server middleware builder with Middleware[http.Handler]. MiddlewareStack is originally a function and calling it with root handler as input gives a handler which runs all pushed Middleware(s) one-by-one in FIFO order.

func (MiddlewareStack[H]) Push added in v0.9.0

func (stk MiddlewareStack[H]) Push(mw Middleware[H]) MiddlewareStack[H]

Push appends the Middleware to the stack and returns the new MiddlewareStack. It's a function composer and Middleware(s) gets called in order of Push that means calling further Push on returning MiddlewareStack appends the Middleware to ehe end, and it gets called after all previously pushed Middleware(s).

type MutableOption added in v1.1.0

type MutableOption[S any] func(s *S)

MutableOption takes S reference and modifies it directly.

func (MutableOption[S]) Apply added in v1.1.0

func (o MutableOption[S]) Apply(s *S) *S

type Option

type Option[S any] interface {
	Apply(s *S) *S
}

Option is a modifier of S. It applies a modification on S and return it. It is intended to perform partial and isolated updates using ApplyOptions. One usage is functional options pattern that is instead of passing a config struct or many arguments to a constructor, you pass a variadic list of functions (options) that modify the internal state. The modifier can implement this interface or can be a function and used as an Option with help of MutableOption and ImmutableOption.

Another use-case is in making object Transformer(s) with optional field modifiers.

The pattern was popularized by Dave Cheney and Rob Pike. For more details visit https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis

Example:

type Server struct {
	Host string
	Port int
	TLS  bool
}

// Constructor with functional options
func NewServer(opts ...Option[Server]) *Server {
	s := &Server{
		Host: "localhost", // default values
		Port: 8080,
		TLS:  false,
	}

	return ApplyOptions(s, opts...)
}

// Individual options

func WithHost(host string) Option[Server] {
	return MutableOption[Server](func(s *Server) {
		s.Host = host
	})
}

func WithPort(port int) Option[Server] {
	return ImmutableOption[Server](func(s Server) Server {
		s.Port = port

		return s
	})
}

func WithTLS(enabled bool) Option[Server] {
	return ImmutableOption[Server](func(s Server) Server {
		s.TLS = enabled

		return s
	})
}

Usage:

s := NewServer(
	WithHost("example.com"),
	WithPort(443),
	WithTLS(true),
)

type Reducer added in v1.0.0

type Reducer[A, E any] interface {
	Reduce(accumulator A, element E) A
}

func ReduceSum added in v1.0.0

func ReduceSum[T cmp.Ordered]() Reducer[T, T]

type ReducerFunc added in v1.0.0

type ReducerFunc[A, E any] func(accumulator A, element E) A

func (ReducerFunc[A, E]) Reduce added in v1.0.0

func (f ReducerFunc[A, E]) Reduce(accumulator A, element E) A

type Transformer

type Transformer[S, D any] func(src S) D

Transformer is any method which converts S to D. It's usable in slice elements transformations, casting and interlayer data structure mapping like mapping entity to dao or dto and vice versa.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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