Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type SafeSlice ¶
type SafeSlice[T any] struct { // contains filtered or unexported fields }
SafeSlice is similar to a slice except it is safe for modification during range-based traversals.
This is done by guaranteeing that there are no changes made to allocations of slices returned by previous calls to 'Get'. That is, only new calls to 'Get' will observe the elements added, removed, or swapped, to the array before that call to 'Get'.
IMPORTANT: See the following examples for safe iteration.
The Go language guarantees that the expression passed to 'range' is evaluated only once. Therefore, the following iteration makes a single call to 'Get' before the iteration begins. As such, the slice being traversed does not observe the added / removed / swapped elements.
a := NewSafeSlice()
for _, x := range a.Get() { a.Append(...) // SAFE }
a := NewSafeSlice()
for _, x := range a.Get() { a.Remove(0) // SAFE }
The following while loop calls 'Get' multiple times, therefore the length of the array is varying between the loops. While this is correct, it's extremely inefficient because this is forcing a 'snapshot' of the array on each call to the pair (Get, Remove), so don't do this.
a := NewSafeSlice()
for len(a.Get()) > 0 { a.Remove(0) // INEFFICIENT; DON'T DO }
The following iteration however is NOT safe because each call to 'Get' observes the removed elements.
a := NewSafeSlice()
for i := 0; i < len(a.Get()); i++ { a.Remove(i) // WRONG and UNSAFE }
This is not safe for concurrent use. This is safe for non-concurrent modification during traversal.
This performs the worst when the calls to 'Get' and 'Remove' are interleaved.
Example ¶
a := safeslice.New[int]() a.Append(1) a.Append(2) a.Append(3) fmt.Printf("%v", a.Get()) for range a.Get() { a.Remove(0) }
Output: [1 2 3]
func (*SafeSlice[T]) Append ¶
func (s *SafeSlice[T]) Append(elem T)
Append adds a new element to the end of this. It is safe to call this during traversal.
func (*SafeSlice[T]) Get ¶
func (s *SafeSlice[T]) Get() []T
Get returns a "snapshot" of the underlying data as a slice. This slice can be iterated and this SafeSlice can be modified during that iteration.