syncutil

package
v0.0.0-...-aa491c9 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2026 License: MIT Imports: 2 Imported by: 0

README

syncutil

Thread-safe generic containers: Slice, Map, and Locker.

Features

  • Generic — fully typed with Go 1.18+ generics, no interface{} assertions
  • RWMutex-based — concurrent reads with exclusive writes (Slice, Map)
  • Range iterationMap.Range with early exit support
  • Atomic updatesLocker.Update for safe read-modify-write on a single value

Installation

go get github.com/sxwebdev/xutils/syncutil

Slice

Thread-safe generic slice:

s := syncutil.NewSlice[string]()
s.Add("hello")
s.AddMany([]string{"world", "!"})

all := s.GetAll() // []string{"hello", "world", "!"}
n := s.Len()      // 3

Pre-allocate with a fixed length:

s := syncutil.NewSliceWithLength[int](10)
s.AddToIndex(0, 42)
Slice API
Method Description
NewSlice[T]() Create empty slice
NewSliceWithLength[T](n) Create with capacity n
Add(item) Append a single item
AddToIndex(i, item) Set item at index
AddMany(items) Append multiple items
GetAll() Return all items
Len() Return size

Map

Thread-safe generic map with iteration:

m := syncutil.NewMap[string, int]()
m.Set("connections", 42)

val, ok := m.Get("connections") // 42, true
m.Has("connections")            // true
m.Delete("connections")

Range iteration with early exit:

m.Range(func(key string, value int) bool {
    fmt.Printf("%s = %d\n", key, value)
    return true // return false to stop
})

Extract keys or values:

keys := m.Keys()     // []string
values := m.Values() // []int
Map API
Method Description
NewMap[K, V]() Create empty map
NewMapWithCapacity[K, V](cap) Create with initial capacity
Set(key, value) Set key-value pair
Get(key) Get value (ok pattern)
Delete(key) Remove key
Has(key) Check key existence
GetAll() Return copy of all items
Keys() Return all keys as slice
Values() Return all values as slice
Range(fn) Iterate with early exit support
Len() Return size
Clear() Remove all items

Locker

Mutex-protected single value with atomic update callback:

l := syncutil.NewLocker(Config{Timeout: 30 * time.Second})

cfg := l.Get()        // read a copy
ptr := l.GetPointer() // read pointer to value

l.Set(Config{Timeout: 60 * time.Second}) // replace

l.Update(func(c *Config) {
    c.Timeout = 90 * time.Second // modify in place under lock
})
Locker API
Method Description
NewLocker(v) Create with initial value
Set(value) Replace value
Get() Read a copy of the value
GetPointer() Get pointer to the value
Update(fn) Modify value in place under lock

Documentation

Overview

Package syncutil provides thread-safe generic containers for concurrent access to slices, maps, and single values.

Core Concepts

Three container types are provided, each wrapping a standard Go data structure with mutex-based synchronization:

  • Slice — thread-safe generic slice (RWMutex)
  • Map — thread-safe generic map with iteration support (RWMutex)
  • Locker — mutex-protected single value with atomic update callback

All containers use generics (Go 1.18+), so values are fully typed without interface{} assertions.

Slice

Slice wraps a Go slice with sync.RWMutex for safe concurrent access:

s := syncutil.NewSlice[string]()
s.Add("hello")
s.AddMany([]string{"world", "!"})

all := s.GetAll() // []string{"hello", "world", "!"}
n := s.Len()      // 3

Use NewSliceWithLength to pre-allocate and set items by index:

s := syncutil.NewSliceWithLength[int](10)
s.AddToIndex(0, 42)

Map

Map wraps a Go map with sync.RWMutex. It supports get, set, delete, existence checks, key/value extraction, and range iteration:

m := syncutil.NewMap[string, int]()
m.Set("connections", 42)

val, ok := m.Get("connections") // 42, true
m.Has("connections")            // true
m.Delete("connections")

Iterate with Map.Range. Return false from the callback to stop early:

m.Range(func(key string, value int) bool {
	fmt.Printf("%s = %d\n", key, value)
	return true // continue
})

Extract keys or values as slices:

keys := m.Keys()     // []string
values := m.Values() // []int

Locker

Locker protects a single value of any type with a sync.Mutex. Use Locker.Update for atomic read-modify-write operations:

l := syncutil.NewLocker(Config{Timeout: 30 * time.Second})

cfg := l.Get()       // read a copy
ptr := l.GetPointer() // read pointer to value

l.Set(Config{Timeout: 60 * time.Second}) // replace

l.Update(func(c *Config) {
	c.Timeout = 90 * time.Second // modify in place under lock
})

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Locker

type Locker[T any] struct {
	// contains filtered or unexported fields
}

Locker is a mutex-protected wrapper for any type (stores a pointer to the value).

func NewLocker

func NewLocker[T any](value T) *Locker[T]

NewLocker creates a new mutex-protected value.

func (*Locker[T]) Get

func (l *Locker[T]) Get() T

Get safely returns a copy of the current value.

func (*Locker[T]) GetPointer

func (l *Locker[T]) GetPointer() *T

GetPointer safely returns a pointer to the current value.

func (*Locker[T]) Set

func (l *Locker[T]) Set(value T)

Set replaces the value atomically.

func (*Locker[T]) Update

func (l *Locker[T]) Update(fn func(value *T))

Update safely modifies the value in-place. The function fn receives a pointer and can modify the value directly.

type Map

type Map[K comparable, V any] struct {
	// contains filtered or unexported fields
}

func NewMap

func NewMap[K comparable, V any]() *Map[K, V]

func NewMapWithCapacity

func NewMapWithCapacity[K comparable, V any](capacity int) *Map[K, V]

func (*Map[K, V]) Clear

func (m *Map[K, V]) Clear()

func (*Map[K, V]) Delete

func (m *Map[K, V]) Delete(key K)

func (*Map[K, V]) Get

func (m *Map[K, V]) Get(key K) (V, bool)

func (*Map[K, V]) GetAll

func (m *Map[K, V]) GetAll() map[K]V

func (*Map[K, V]) Has

func (m *Map[K, V]) Has(key K) bool

func (*Map[K, V]) Keys

func (m *Map[K, V]) Keys() []K

func (*Map[K, V]) Len

func (m *Map[K, V]) Len() int

func (*Map[K, V]) Range

func (m *Map[K, V]) Range(fn func(key K, value V) bool)

Range calls fn for each key-value pair in the map. If fn returns false, iteration stops. The map is read-locked for the duration of the iteration.

func (*Map[K, V]) Set

func (m *Map[K, V]) Set(key K, value V)

func (*Map[K, V]) Values

func (m *Map[K, V]) Values() []V

type Slice

type Slice[T any] struct {
	// contains filtered or unexported fields
}

func NewSlice

func NewSlice[T any]() *Slice[T]

func NewSliceWithLength

func NewSliceWithLength[T any](length int) *Slice[T]

func (*Slice[T]) Add

func (s *Slice[T]) Add(item T)

func (*Slice[T]) AddMany

func (s *Slice[T]) AddMany(items []T)

func (*Slice[T]) AddToIndex

func (s *Slice[T]) AddToIndex(index int, item T)

func (*Slice[T]) GetAll

func (s *Slice[T]) GetAll() []T

func (*Slice[T]) Len

func (s *Slice[T]) Len() int

Jump to

Keyboard shortcuts

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