2026-01-20 22:08:36 +00:00
|
|
|
|
package csmap
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"encoding/json"
|
|
|
|
|
|
"sync"
|
2026-02-22 10:59:41 +08:00
|
|
|
|
"sync/atomic"
|
2026-01-20 22:08:36 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// CsMap 基于官方 sync.Map 重构,完全兼容原有接口
|
2026-01-20 22:08:36 +00:00
|
|
|
|
type CsMap[K comparable, V any] struct {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
inner sync.Map // 核心替换为官方 sync.Map
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 以下配置方法保留(兼容原有调用方式,但内部无实际作用)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
type OptFunc[K comparable, V any] func(o *CsMap[K, V])
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// New 创建基于 sync.Map 的并发安全 Map,兼容原有配置参数(参数无实际作用)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func New[K comparable, V any](options ...OptFunc[K, V]) *CsMap[K, V] {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
m := &CsMap[K, V]{}
|
|
|
|
|
|
// 遍历配置项(兼容原有代码,无实际逻辑)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
for _, option := range options {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
option(m)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
2026-02-25 13:20:38 +08:00
|
|
|
|
return m
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 保留原有配置方法(空实现,保证接口兼容)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func WithShardCount[K comparable, V any](count uint64) func(csMap *CsMap[K, V]) {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
return func(csMap *CsMap[K, V]) {}
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func WithCustomHasher[K comparable, V any](h func(key K) uint64) func(csMap *CsMap[K, V]) {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
return func(csMap *CsMap[K, V]) {}
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func WithSize[K comparable, V any](size uint64) func(csMap *CsMap[K, V]) {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
return func(csMap *CsMap[K, V]) {}
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// -------------------------- 核心操作方法(基于 sync.Map 实现) --------------------------
|
2026-01-20 22:08:36 +00:00
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// Store 存储键值对,兼容原有接口
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) Store(key K, value V) {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
m.inner.Store(key, value)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
2026-03-16 22:30:12 +08:00
|
|
|
|
func (m *CsMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
|
|
|
|
|
|
T, OK := m.inner.LoadOrStore(key, value)
|
|
|
|
|
|
return T.(V), OK
|
|
|
|
|
|
}
|
2026-01-20 22:08:36 +00:00
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// Delete 删除指定键,返回是否删除成功
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) Delete(key K) bool {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// sync.Map.Delete 无返回值,需先 Load 判断是否存在
|
|
|
|
|
|
_, ok := m.inner.Load(key)
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
m.inner.Delete(key)
|
|
|
|
|
|
}
|
|
|
|
|
|
return ok
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// DeleteIf 满足条件时删除
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) DeleteIf(key K, condition func(value V) bool) bool {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 先 Load 获取值,再判断条件
|
|
|
|
|
|
val, ok := m.inner.Load(key)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
v, okCast := val.(V)
|
|
|
|
|
|
if !okCast {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if condition(v) {
|
|
|
|
|
|
m.inner.Delete(key)
|
|
|
|
|
|
return true
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// Load 获取指定键的值
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) Load(key K) (V, bool) {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
var zero V
|
|
|
|
|
|
val, ok := m.inner.Load(key)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return zero, false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 类型断言(保证类型安全)
|
|
|
|
|
|
v, okCast := val.(V)
|
|
|
|
|
|
if !okCast {
|
|
|
|
|
|
return zero, false
|
|
|
|
|
|
}
|
|
|
|
|
|
return v, true
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// Has 判断键是否存在
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) Has(key K) bool {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
_, ok := m.inner.Load(key)
|
|
|
|
|
|
return ok
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// Clear 清空所有数据
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) Clear() {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// sync.Map 无直接 Clear 方法,通过 Range 遍历删除
|
|
|
|
|
|
m.inner.Range(func(key, value any) bool {
|
|
|
|
|
|
m.inner.Delete(key)
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// Count 统计元素数量
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) Count() int {
|
|
|
|
|
|
count := 0
|
2026-02-25 13:20:38 +08:00
|
|
|
|
m.inner.Range(func(key, value any) bool {
|
|
|
|
|
|
count++
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
2026-01-20 22:08:36 +00:00
|
|
|
|
return count
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// SetIfAbsent 仅当键不存在时设置值
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) SetIfAbsent(key K, value V) {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
m.inner.LoadOrStore(key, value)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// SetIf 根据条件设置值
|
|
|
|
|
|
func (m *CsMap[K, V]) SetIf(key K, conditionFn func(previousValue V, previousFound bool) (value V, set bool)) {
|
|
|
|
|
|
prevVal, found := m.inner.Load(key)
|
|
|
|
|
|
var prevV V
|
|
|
|
|
|
if found {
|
|
|
|
|
|
prevV, _ = prevVal.(V)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 执行条件函数
|
|
|
|
|
|
newVal, set := conditionFn(prevV, found)
|
|
|
|
|
|
if set {
|
|
|
|
|
|
m.inner.Store(key, newVal)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// SetIfPresent 仅当键存在时设置值
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) SetIfPresent(key K, value V) {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 先判断是否存在,再设置
|
|
|
|
|
|
if _, ok := m.inner.Load(key); ok {
|
|
|
|
|
|
m.inner.Store(key, value)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// IsEmpty 判断是否为空
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) IsEmpty() bool {
|
|
|
|
|
|
return m.Count() == 0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// Tuple 保留原有结构体(兼容序列化逻辑)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
type Tuple[K comparable, V any] struct {
|
|
|
|
|
|
Key K
|
|
|
|
|
|
Val V
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// -------------------------- 关键修复:Range 方法(无锁阻塞风险) --------------------------
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) Range(f func(key K, value V) (stop bool)) {
|
2026-02-22 10:59:41 +08:00
|
|
|
|
if f == nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-01-20 22:08:36 +00:00
|
|
|
|
|
2026-02-22 10:59:41 +08:00
|
|
|
|
var stopFlag atomic.Bool
|
2026-01-20 22:08:36 +00:00
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 基于 sync.Map 的 Range 实现,无额外 goroutine/channel
|
|
|
|
|
|
m.inner.Range(func(key, value any) bool {
|
|
|
|
|
|
// 检测终止标志
|
2026-02-22 10:59:41 +08:00
|
|
|
|
if stopFlag.Load() {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
return false
|
2026-02-22 10:59:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 类型断言
|
|
|
|
|
|
k, okK := key.(K)
|
|
|
|
|
|
v, okV := value.(V)
|
|
|
|
|
|
if !okK || !okV {
|
|
|
|
|
|
return true // 类型不匹配时跳过,继续遍历
|
|
|
|
|
|
}
|
2026-02-22 10:59:41 +08:00
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 执行用户回调
|
|
|
|
|
|
if f(k, v) {
|
|
|
|
|
|
stopFlag.Store(true)
|
|
|
|
|
|
return false // 终止遍历
|
|
|
|
|
|
}
|
|
|
|
|
|
return true
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2026-02-22 10:59:41 +08:00
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// -------------------------- 序列化方法(兼容原有逻辑) --------------------------
|
2026-01-20 22:08:36 +00:00
|
|
|
|
func (m *CsMap[K, V]) MarshalJSON() ([]byte, error) {
|
|
|
|
|
|
tmp := make(map[K]V, m.Count())
|
|
|
|
|
|
m.Range(func(key K, value V) (stop bool) {
|
|
|
|
|
|
tmp[key] = value
|
|
|
|
|
|
return false
|
|
|
|
|
|
})
|
|
|
|
|
|
return json.Marshal(tmp)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (m *CsMap[K, V]) UnmarshalJSON(b []byte) error {
|
2026-02-25 13:20:38 +08:00
|
|
|
|
tmp := make(map[K]V)
|
2026-01-20 22:08:36 +00:00
|
|
|
|
if err := json.Unmarshal(b, &tmp); err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// 清空原有数据
|
|
|
|
|
|
m.Clear()
|
|
|
|
|
|
// 批量存储
|
2026-01-20 22:08:36 +00:00
|
|
|
|
for key, val := range tmp {
|
|
|
|
|
|
m.Store(key, val)
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-25 13:20:38 +08:00
|
|
|
|
// -------------------------- 移除所有无用的旧方法(produce/listen 等) --------------------------
|