Documentation
¶
Overview ¶
Package container provides common container types.
TODO(a.garipov): Consider adding a set interface.
TODO(a.garipov): Consider adding a intersect and union operations on sets.
Index ¶
- func MapSetToString[T constraints.Ordered](set *MapSet[T]) (s string)
- func MapSetToStringFunc[T comparable](set *MapSet[T], compare func(a, b T) (res int)) (s string)
- type KeyValue
- type KeyValues
- type MapSet
- func (set *MapSet[T]) Add(v T)
- func (set *MapSet[T]) Clear()
- func (set *MapSet[T]) Clone() (clone *MapSet[T])
- func (set *MapSet[T]) Delete(v T)
- func (set *MapSet[T]) Equal(other *MapSet[T]) (ok bool)
- func (set *MapSet[T]) Has(v T) (ok bool)
- func (set *MapSet[T]) Len() (n int)
- func (set *MapSet[T]) Range(f func(v T) (cont bool))
- func (set *MapSet[T]) Values() (values []T)
- type RingBuffer
- type SortedSliceSet
- func (set *SortedSliceSet[T]) Add(v T)
- func (set *SortedSliceSet[T]) Clear()
- func (set *SortedSliceSet[T]) Clone() (clone *SortedSliceSet[T])
- func (set *SortedSliceSet[T]) Delete(v T)
- func (set *SortedSliceSet[T]) Equal(other *SortedSliceSet[T]) (ok bool)
- func (set *SortedSliceSet[T]) Has(v T) (ok bool)
- func (set *SortedSliceSet[T]) Len() (n int)
- func (set *SortedSliceSet[T]) Range(f func(v T) (cont bool))
- func (set *SortedSliceSet[T]) String() (s string)
- func (set *SortedSliceSet[T]) Values() (values []T)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MapSetToString ¶
func MapSetToString[T constraints.Ordered](set *MapSet[T]) (s string)
MapSetToString converts a *MapSet of values of an ordered type into a reproducible string.
func MapSetToStringFunc ¶
func MapSetToStringFunc[T comparable](set *MapSet[T], compare func(a, b T) (res int)) (s string)
MapSetToStringFunc is like MapSetToString but uses an explicit comparison function.
Types ¶
type KeyValue ¶ added in v0.25.3
type KeyValue[K comparable, V any] struct { Key K Value V }
KeyValue is a simple structure for pairs of values where one identifies the other. It is useful when multiple values need to be processed in a defined order and each value is associated with its own name or ID.
type KeyValues ¶ added in v0.25.3
type KeyValues[K comparable, V any] []KeyValue[K, V]
KeyValues is a slice of [KeyValue]s.
Example ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { type service struct{} var ( serviceA = service{} serviceB = service{} serviceC = service{} ) type svcName string validate := func(_ service) (err error) { return nil } // These should be validated in this order. services := container.KeyValues[svcName, service]{{ Key: "svc_a", Value: serviceA, }, { Key: "svc_b", Value: serviceB, }, { Key: "svc_c", Value: serviceC, }} for _, kv := range services { fmt.Printf("validating service %q: %v\n", kv.Key, validate(kv.Value)) } }
Output: validating service "svc_a": <nil> validating service "svc_b": <nil> validating service "svc_c": <nil>
type MapSet ¶
type MapSet[T comparable] struct { // contains filtered or unexported fields }
MapSet is a set that uses a map as its storage.
TODO(a.garipov): Figure out a way to add a reproducible String method.
Example ¶
package main import ( "fmt" "slices" "github.com/AdguardTeam/golibs/container" ) func main() { const x = 1 set := container.NewMapSet[int]() ok := set.Has(x) fmt.Printf("%s contains %v is %t\n", container.MapSetToString(set), x, ok) set.Add(x) ok = set.Has(x) fmt.Printf("%s contains %v is %t\n", container.MapSetToString(set), x, ok) other := container.NewMapSet(x) ok = set.Equal(other) fmt.Printf( "%s is equal to %s is %t\n", container.MapSetToString(set), container.MapSetToString(other), ok, ) set.Add(2) values := set.Values() slices.Sort(values) fmt.Printf("values of %s are %v\n", container.MapSetToString(set), values) set.Delete(x) ok = set.Has(x) fmt.Printf("%s contains %v is %t\n", container.MapSetToString(set), x, ok) set.Range(func(n int) (cont bool) { fmt.Printf("got value %d\n", n) return false }) set = container.NewMapSet(x) fmt.Printf("%s has length %d\n", container.MapSetToString(set), set.Len()) set.Clear() fmt.Printf("%s has length %d\n", container.MapSetToString(set), set.Len()) }
Output: [] contains 1 is false [1] contains 1 is true [1] is equal to [1] is true values of [1 2] are [1 2] [2] contains 1 is false got value 2 [1] has length 1 [] has length 0
Example (Nil) ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { const x = 1 var set *container.MapSet[int] panicked := false setPanicked := func() { panicked = recover() != nil } func() { defer setPanicked() set.Clear() }() fmt.Printf("panic after clear: %t\n", panicked) func() { defer setPanicked() set.Delete(x) }() fmt.Printf("panic after delete: %t\n", panicked) func() { defer setPanicked() set.Has(x) }() fmt.Printf("panic after has: %t\n", panicked) func() { defer setPanicked() set.Len() }() fmt.Printf("panic after len: %t\n", panicked) func() { defer setPanicked() set.Range(func(n int) (cont bool) { fmt.Printf("got value %d\n", n) return true }) }() fmt.Printf("panic after range: %t\n", panicked) func() { defer setPanicked() set.Values() }() fmt.Printf("panic after values: %t\n", panicked) func() { defer setPanicked() set.Add(x) }() fmt.Printf("panic after add: %t\n", panicked) }
Output: panic after clear: false panic after delete: false panic after has: false panic after len: false panic after range: false panic after values: false panic after add: true
func NewMapSet ¶
func NewMapSet[T comparable](values ...T) (set *MapSet[T])
NewMapSet returns a new map set containing values.
func (*MapSet[T]) Clear ¶
func (set *MapSet[T]) Clear()
Clear clears set in a way that retains the internal storage for later reuse to reduce allocations. Calling Clear on a nil set has no effect, just like a clear on a nil map doesn't.
func (*MapSet[T]) Clone ¶
Clone returns a deep clone of set. If set is nil, clone is nil.
Example ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { var set *container.MapSet[int] fmt.Printf("nil: %#v\n", set.Clone()) const x, y = 1, 2 set = container.NewMapSet(x) clone := set.Clone() clone.Add(y) fmt.Printf("orig: %t %t\n", set.Has(x), set.Has(y)) fmt.Printf("clone: %t %t\n", clone.Has(x), clone.Has(y)) }
Output: nil: (*container.MapSet[int])(nil) orig: true false clone: true true
func (*MapSet[T]) Delete ¶
func (set *MapSet[T]) Delete(v T)
Delete deletes v from set. Calling Delete on a nil set has no effect, just like delete on a nil map doesn't.
func (*MapSet[T]) Equal ¶
Equal returns true if set is equal to other. set and other may be nil; Equal returns true if both are nil, but a nil *MapSet is not equal to a non-nil empty one.
Example ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { const x, y = 1, 2 set := container.NewMapSet(x) fmt.Printf("same: %t\n", set.Equal(container.NewMapSet(x))) fmt.Printf("other elem: %t\n", set.Equal(container.NewMapSet(y))) fmt.Printf("other len: %t\n", set.Equal(container.NewMapSet(x, y))) fmt.Printf("nil: %t\n", set.Equal(nil)) fmt.Printf("nil eq nil: %t\n", (*container.MapSet[int])(nil).Equal(nil)) }
Output: same: true other elem: false other len: false nil: false nil eq nil: true
func (*MapSet[T]) Has ¶
Has returns true if v is in set. Calling Has on a nil set returns false, just like indexing on an empty map does.
func (*MapSet[T]) Len ¶
Len returns the length of set. A nil set has a length of zero, just like an empty map.
type RingBuffer ¶ added in v0.25.2
type RingBuffer[T any] struct { // contains filtered or unexported fields }
RingBuffer is the generic implementation of ring buffer data structure.
func NewRingBuffer ¶ added in v0.25.2
func NewRingBuffer[T any](size uint) (rb *RingBuffer[T])
NewRingBuffer initializes a new ring buffer with the given size.
func (*RingBuffer[T]) Clear ¶ added in v0.25.2
func (rb *RingBuffer[T]) Clear()
Clear clears the buffer.
func (*RingBuffer[T]) Current ¶ added in v0.25.2
func (rb *RingBuffer[T]) Current() (e T)
Current returns the element at the current position. It returns zero value of T if rb is nil or empty.
Example ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { const size, x, y, z = 2, 1, 2, 3 var rb *container.RingBuffer[int] fmt.Printf("nil: %#v\n", rb.Current()) rb = container.NewRingBuffer[int](size) fmt.Printf("empty: %#v\n", rb.Current()) rb.Push(x) fmt.Printf("push %d: %#v\n", x, rb.Current()) rb.Push(y) fmt.Printf("push %d: %#v\n", y, rb.Current()) rb.Push(z) fmt.Printf("push %d: %#v\n", z, rb.Current()) fmt.Printf("current: %#v\n", rb.Current()) }
Output: nil: 0 empty: 0 push 1: 0 push 2: 1 push 3: 2 current: 2
func (*RingBuffer[T]) Len ¶ added in v0.25.2
func (rb *RingBuffer[T]) Len() (l uint)
Len returns a length of the buffer.
func (*RingBuffer[T]) Push ¶ added in v0.25.2
func (rb *RingBuffer[T]) Push(e T)
Push adds an element to the buffer and sets the current position to the next element.
func (*RingBuffer[T]) Range ¶ added in v0.25.2
func (rb *RingBuffer[T]) Range(f func(T) (cont bool))
Range calls f for each element of the buffer starting from the current position until f returns false.
func (*RingBuffer[T]) ReverseRange ¶ added in v0.25.2
func (rb *RingBuffer[T]) ReverseRange(f func(T) (cont bool))
ReverseRange calls f for each element of the buffer in reverse order ending with the current position until f returns false.
type SortedSliceSet ¶ added in v0.30.1
SortedSliceSet is a simple set implementation that has a sorted set of values as its underlying storage.
TODO(a.garipov): Consider relaxing the type requirement or adding a version with a comparison function.
Example ¶
package main import ( "fmt" "slices" "github.com/AdguardTeam/golibs/container" ) func main() { const x = 1 set := container.NewSortedSliceSet[int]() ok := set.Has(x) fmt.Printf("%s contains %v is %t\n", set, x, ok) set.Add(x) ok = set.Has(x) fmt.Printf("%s contains %v is %t\n", set, x, ok) other := container.NewSortedSliceSet(x) ok = set.Equal(other) fmt.Printf("%s is equal to %s is %t\n", set, other, ok) set.Add(2) values := set.Values() slices.Sort(values) fmt.Printf("values of %s are %v\n", set, values) set.Delete(x) ok = set.Has(x) fmt.Printf("%s contains %v is %t\n", set, x, ok) set.Range(func(n int) (cont bool) { fmt.Printf("got value %d\n", n) return false }) set = container.NewSortedSliceSet(x) fmt.Printf("%s has length %d\n", set, set.Len()) set.Clear() fmt.Printf("%s has length %d\n", set, set.Len()) }
Output: [] contains 1 is false [1] contains 1 is true [1] is equal to [1] is true values of [1 2] are [1 2] [2] contains 1 is false got value 2 [1] has length 1 [] has length 0
Example (Nil) ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { const x = 1 var set *container.SortedSliceSet[int] panicked := false setPanicked := func() { panicked = recover() != nil } func() { defer setPanicked() set.Clear() }() fmt.Printf("panic after clear: %t\n", panicked) func() { defer setPanicked() set.Delete(x) }() fmt.Printf("panic after delete: %t\n", panicked) func() { defer setPanicked() set.Has(x) }() fmt.Printf("panic after has: %t\n", panicked) func() { defer setPanicked() set.Len() }() fmt.Printf("panic after len: %t\n", panicked) func() { defer setPanicked() set.Range(func(n int) (cont bool) { fmt.Printf("got value %d\n", n) return true }) }() fmt.Printf("panic after range: %t\n", panicked) func() { defer setPanicked() set.Values() }() fmt.Printf("panic after values: %t\n", panicked) func() { defer setPanicked() set.Add(x) }() fmt.Printf("panic after add: %t\n", panicked) }
Output: panic after clear: false panic after delete: true panic after has: false panic after len: false panic after range: false panic after values: false panic after add: true
func NewSortedSliceSet ¶ added in v0.30.1
func NewSortedSliceSet[T cmp.Ordered](elems ...T) (set *SortedSliceSet[T])
NewSortedSliceSet returns a new *SortedSliceSet. elems must not be modified after calling NewSortedSliceSet.
func (*SortedSliceSet[T]) Add ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Add(v T)
Add adds v to set.
func (*SortedSliceSet[T]) Clear ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Clear()
Clear clears set in a way that retains the internal storage for later reuse to reduce allocations. Calling Clear on a nil set has no effect, just like a clear on a nil slice doesn't.
func (*SortedSliceSet[T]) Clone ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Clone() (clone *SortedSliceSet[T])
Clone returns a clone of set. If set is nil, clone is nil.
NOTE: It calls slices.Clone on the underlying storage, so these elements are cloned shallowly.
Example ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { var set *container.SortedSliceSet[int] fmt.Printf("nil: %#v\n", set.Clone()) const x, y = 1, 2 set = container.NewSortedSliceSet(x) clone := set.Clone() clone.Add(y) fmt.Printf("orig: %t %t\n", set.Has(x), set.Has(y)) fmt.Printf("clone: %t %t\n", clone.Has(x), clone.Has(y)) }
Output: nil: (*container.SortedSliceSet[int])(nil) orig: true false clone: true true
func (*SortedSliceSet[T]) Delete ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Delete(v T)
Delete deletes v from set.
func (*SortedSliceSet[T]) Equal ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Equal(other *SortedSliceSet[T]) (ok bool)
Equal returns true if set is equal to other. set and other may be nil; Equal returns true if both are nil, but a nil *SortedSliceSet is not equal to a non-nil empty one.
Example ¶
package main import ( "fmt" "github.com/AdguardTeam/golibs/container" ) func main() { const x, y = 1, 2 set := container.NewSortedSliceSet(x) fmt.Printf("same: %t\n", set.Equal(container.NewSortedSliceSet(x))) fmt.Printf("other elem: %t\n", set.Equal(container.NewSortedSliceSet(y))) fmt.Printf("other len: %t\n", set.Equal(container.NewSortedSliceSet(x, y))) fmt.Printf("nil: %t\n", set.Equal(nil)) fmt.Printf("nil eq nil: %t\n", (*container.SortedSliceSet[int])(nil).Equal(nil)) }
Output: same: true other elem: false other len: false nil: false nil eq nil: true
func (*SortedSliceSet[T]) Has ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Has(v T) (ok bool)
Has returns true if v is in set. Calling Has on a nil set returns false, just like iterating over a nil or empty slice does.
func (*SortedSliceSet[T]) Len ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Len() (n int)
Len returns the length of set. A nil set has a length of zero, just like an nil or empty slice.
func (*SortedSliceSet[T]) Range ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Range(f func(v T) (cont bool))
Range calls f with each value of set in their sorted order. If cont is false, Range stops the iteration. Calling Range on a nil *SortedSliceSet has no effect.
func (*SortedSliceSet[T]) String ¶ added in v0.30.1
func (set *SortedSliceSet[T]) String() (s string)
String implements the fmt.Stringer interface for *SortedSliceSet. Calling String on a nil *SortedSliceSet does not panic.
func (*SortedSliceSet[T]) Values ¶ added in v0.30.1
func (set *SortedSliceSet[T]) Values() (values []T)
Values returns the underlying slice of set. values must not be modified. Values returns nil if set is nil.