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 ¶
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 ¶
type KeyValues[K comparable, V any] []KeyValue[K, V]
KeyValues is a slice of [KeyValue]s.
Example ¶
package main
import (
"fmt"
"github.com/sleepybrace/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/sleepybrace/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/sleepybrace/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/sleepybrace/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/sleepybrace/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 ¶
type RingBuffer[T any] struct { // contains filtered or unexported fields }
RingBuffer is the generic implementation of ring buffer data structure.
func NewRingBuffer ¶
func NewRingBuffer[T any](size uint) (rb *RingBuffer[T])
NewRingBuffer initializes a new ring buffer with the given size.
func (*RingBuffer[T]) Current ¶
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/sleepybrace/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 ¶
func (rb *RingBuffer[T]) Len() (l uint)
Len returns a length of the buffer.
func (*RingBuffer[T]) Push ¶
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 ¶
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 ¶
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 ¶
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/sleepybrace/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/sleepybrace/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 ¶
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]) Clear ¶
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 ¶
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/sleepybrace/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 ¶
func (set *SortedSliceSet[T]) Delete(v T)
Delete deletes v from set.
func (*SortedSliceSet[T]) Equal ¶
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/sleepybrace/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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.