syncx

package
v1.24.0 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package syncx 提供泛型并发数据结构,是标准库 sync 包的类型安全扩展。

目前提供:

  • Map:基于 RWMutex 的泛型并发映射,API 对齐 sync.Map 并扩展 Compute 等方法。
  • Lazy:基于 sync.Once 的泛型懒初始化容器。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type GroupStateStore

type GroupStateStore[T any] struct {
	Map[string, *T]
}

GroupStateStore 是泛型的 per-group 状态管理器,基于 Map[string, *T] 构建。

相比直接使用 Map[string, *T],额外提供无参的 GroupStateStore.GetOrCreate 便捷方法 (自动以 new(T) 作为缺失 key 的构造函数,无需调用方传入工厂函数)。

其余方法(Load / Delete / DeleteIf / Range / Len 等)由嵌入的 Map 直接提供, 不再重复实现。

典型用法(词语接龙/钓鱼/游戏等 per-group 状态):

type gameState struct {
    mu     sync.Mutex
    active bool
    round  int
}

var store syncx.GroupStateStore[gameState]

state := store.GetOrCreate(groupID)
state.mu.Lock()
defer state.mu.Unlock()
state.active = true

注意:T 本身的并发保护由调用方负责(通常在 T 内内嵌 sync.Mutex)。 零值直接可用,使用后不得复制。

func (*GroupStateStore[T]) Get

func (s *GroupStateStore[T]) Get(groupID string) (*T, bool)

Get 是 Map.Load 的别名

func (*GroupStateStore[T]) GetOrCreate

func (s *GroupStateStore[T]) GetOrCreate(groupID string) *T

GetOrCreate 返回 groupID 对应的状态指针。

若该 groupID 不存在,自动创建零值 *T 并存储后返回。 多个 goroutine 并发调用是安全的;同一 key 只会创建一次。

type Lazy

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

Lazy 提供泛型懒初始化:首次调用 Lazy.Get 时执行 init 函数, 结果被缓存,后续调用直接返回缓存值,无额外锁开销。

使用 NewLazy 构造;零值不可用(init 为 nil 会 panic)。

示例:

loader := syncx.NewLazy(func() *Config {
    cfg, _ := loadConfigFromDisk()
    return cfg
})
// 首次调用触发加载,后续调用直接返回缓存:
cfg := loader.Get()

func NewLazy

func NewLazy[T any](init func() T) *Lazy[T]

NewLazy 创建一个懒初始化容器。 init 在首次调用 Lazy.Get 时执行,且仅执行一次(并发安全)。

func (*Lazy[T]) Get

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

Get 返回初始化后的值。 首次调用时执行 init(其它并发 Get 调用阻塞直至完成),后续调用直接返回缓存值。

type Map

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

Map 是基于 sync.RWMutex 的泛型并发映射。

相比 sync.Map,提供编译期类型安全(无需运行时类型断言), 并附加 Map.ComputeMap.LenMap.HasMap.Clear 等实用方法。

零值直接可用,无需显式初始化。Map 在首次使用后不得复制。

适用场景:

  • 混合读写负载,通过 RWMutex 实现并发安全。
  • 需要原子读-改-写操作(Map.Compute)。
  • 消除 mu sync.RWMutex + map[K]V 模板样板代码。

示例:

var m syncx.Map[string, int]
m.Store("a", 1)
v, ok := m.Load("a")  // v=1, ok=true
m.Compute("a", func(old int, exists bool) (int, bool) {
    return old + 1, true  // 原子自增
})

func (*Map[K, V]) Clear

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

Clear 删除所有键值对。

func (*Map[K, V]) Compute

func (m *Map[K, V]) Compute(key K, fn func(old V, exists bool) (newVal V, store bool)) (V, bool)

Compute 在持有写锁的情况下对 key 执行原子读-改-写操作。

fn 接收当前值 old 及是否存在 exists,返回:

  • (newVal, true) → 将 newVal 写入 map
  • (_, false) → 从 map 删除 key(key 不存在时为空操作)

返回 fn 的返回值 (newVal, store),供调用方检查最终状态。 若需在调用方获取额外结果,可在 fn 内通过闭包捕获变量。

func (*Map[K, V]) Delete

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

Delete 删除 key;若 key 不存在则为空操作。

func (*Map[K, V]) DeleteIf

func (m *Map[K, V]) DeleteIf(fn func(key K, val V) bool)

DeleteIf 按条件批量删除条目。

遍历所有条目,当 fn 返回 true 时删除该条目。 fn 在持有写锁期间调用,因此 fn 内部不应再操作同一 Map(会死锁)。

典型用途:定期 GC 超时的游戏会话。

store.DeleteIf(func(_ string, s *gameState) bool {
    s.mu.Lock()
    defer s.mu.Unlock()
    return time.Since(s.StartTime) > 5*time.Minute
})

func (*Map[K, V]) GetOrCreate

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

GetOrCreate 返回 key 对应的值;若 key 不存在,则调用 newFn 创建、存储并返回新值。

使用读写双检锁(read→write double-check)保证并发安全: 快路径仅需读锁,只有真正缺失时才升级写锁,并发创建只发生一次。

newFn 在持有写锁时调用,不应在 newFn 内再操作同一 Map(会死锁)。

func (*Map[K, V]) Has

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

Has 报告 key 是否存在。

func (*Map[K, V]) Len

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

Len 返回当前条目数。

func (*Map[K, V]) Load

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

Load 返回 key 对应的值及是否存在。

func (*Map[K, V]) LoadAndDelete

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

LoadAndDelete 删除 key 并返回删除前的值及是否存在。

func (*Map[K, V]) LoadOrStore

func (m *Map[K, V]) LoadOrStore(key K, val V) (actual V, loaded bool)

LoadOrStore 若 key 已存在则返回现有值(loaded=true), 否则存入 val 并返回 val(loaded=false)。

func (*Map[K, V]) Range

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

Range 遍历所有键值对,顺序不确定。若 fn 返回 false,提前终止迭代。

Range 在调用时先对内部 map 做浅拷贝快照,随后释放读锁再迭代。 因此 fn 内部可以安全地调用 Store / Delete / Compute 等方法,不会死锁。

注意:由于快照语义,在 Range 执行期间对 Map 的修改不会反映到本次迭代中。

func (*Map[K, V]) Store

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

Store 存储键值对。

Jump to

Keyboard shortcuts

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