github.com/sandwich-go/boost@v1.3.29/xcontainer/templates/syncmap/syncmap.go (about) 1 // syncmap 提供了一个同步的映射实现,允许安全并发的访问 2 package syncmap 3 4 import ( 5 "sort" 6 "sync" 7 ) 8 9 //template type SyncMap(KType,VType) 10 11 type KType string 12 type VType interface{} 13 14 // SyncMap 定义并发安全的映射,使用 sync.Map 来实现 15 type SyncMap struct { 16 sm sync.Map 17 locker sync.RWMutex 18 } 19 20 // NewSyncMap 构造函数,返回一个新的 SyncMap 21 func NewSyncMap() *SyncMap { 22 return &SyncMap{} 23 } 24 25 // Keys 获取映射中的所有键,返回一个 Key 类型的切片 26 func (s *SyncMap) Keys() (ret []KType) { 27 s.sm.Range(func(key, value interface{}) bool { 28 ret = append(ret, key.(KType)) 29 return true 30 }) 31 return ret 32 } 33 34 // Len 获取映射中键值对的数量 35 func (s *SyncMap) Len() (c int) { 36 s.sm.Range(func(key, value interface{}) bool { 37 c++ 38 return true 39 }) 40 return c 41 } 42 43 // Contains 检查映射中是否包含指定键 44 func (s *SyncMap) Contains(key KType) (ok bool) { 45 _, ok = s.Load(key) 46 return 47 } 48 49 // Get 获取映射中的值 50 func (s *SyncMap) Get(key KType) (value VType) { 51 value, _ = s.Load(key) 52 return 53 } 54 55 // Load 获取映射中的值和是否成功加载的标志 56 func (s *SyncMap) Load(key KType) (value VType, loaded bool) { 57 if v, ok := s.sm.Load(key); ok { 58 return v.(VType), true 59 } 60 return 61 } 62 63 // DeleteMultiple 删除映射中的多个键 64 func (s *SyncMap) DeleteMultiple(keys ...KType) { 65 for _, k := range keys { 66 s.sm.Delete(k) 67 } 68 } 69 70 // Clear 清空映射 71 func (s *SyncMap) Clear() { 72 s.sm.Range(func(key, value interface{}) bool { 73 s.sm.Delete(key) 74 return true 75 }) 76 } 77 78 // Delete 删除映射中的值 79 func (s *SyncMap) Delete(key KType) { s.sm.Delete(key) } 80 81 // Store 往映射中存储一个键值对 82 func (s *SyncMap) Store(key KType, val VType) { s.sm.Store(key, val) } 83 84 // LoadAndDelete 获取映射中的值,并将其从映射中删除 85 func (s *SyncMap) LoadAndDelete(key KType) (value VType, loaded bool) { 86 if v, ok := s.sm.LoadAndDelete(key); ok { 87 return v.(VType), true 88 } 89 return 90 } 91 92 // GetOrSetFuncErrorLock 函数根据key查找值,如果key存在则返回对应的值,否则用cf函数计算得到一个新的值,存储到 SyncMap 中并返回。 93 // 如果执行cf函数时出错,则返回error。 94 // 函数内部使用读写锁实现并发安全 95 func (s *SyncMap) GetOrSetFuncErrorLock(key KType, cf func(key KType) (VType, error)) (value VType, loaded bool, err error) { 96 return s.LoadOrStoreFuncErrorLock(key, cf) 97 } 98 99 // LoadOrStoreFuncErrorLock 函数根据key查找值,如果key存在则返回对应的值,否则用cf函数计算得到一个新的值,存储到 SyncMap 中并返回。 100 // 如果执行cf函数时出错,则返回error。 101 // 函数内部使用读写锁实现并发安全 102 func (s *SyncMap) LoadOrStoreFuncErrorLock(key KType, cf func(key KType) (VType, error)) (value VType, loaded bool, err error) { 103 if v, ok := s.Load(key); ok { 104 return v, true, nil 105 } 106 // 如果不存在,则加写锁,再次查找,如果获取到则直接返回 107 s.locker.Lock() 108 defer s.locker.Unlock() 109 // 再次重试,如果获取到则直接返回 110 if v, ok := s.Load(key); ok { 111 return v, true, nil 112 } 113 // 如果还是不存在,则执行cf函数计算出value,并存储到 SyncMap 中 114 value, err = cf(key) 115 if err != nil { 116 return value, false, err 117 } 118 s.Store(key, value) 119 return value, false, nil 120 } 121 122 // GetOrSetFuncLock 根据key获取对应的value,若不存在则通过cf回调创建value并存储 123 func (s *SyncMap) GetOrSetFuncLock(key KType, cf func(key KType) VType) (value VType, loaded bool) { 124 return s.LoadOrStoreFuncLock(key, cf) 125 } 126 127 // LoadOrStoreFuncLock 根据key获取对应的value,若不存在则通过cf回调创建value并存储 128 func (s *SyncMap) LoadOrStoreFuncLock(key KType, cf func(key KType) VType) (value VType, loaded bool) { 129 value, loaded, _ = s.LoadOrStoreFuncErrorLock(key, func(key KType) (VType, error) { 130 return cf(key), nil 131 }) 132 return value, loaded 133 } 134 135 // LoadOrStore 存储一个 key-value 对,若key已存在则返回已存在的value 136 func (s *SyncMap) LoadOrStore(key KType, val VType) (VType, bool) { 137 actual, ok := s.sm.LoadOrStore(key, val) 138 return actual.(VType), ok 139 } 140 141 // Range 遍历映射中的 key-value 对,对每个 key-value 对执行给定的函数f 142 func (s *SyncMap) Range(f func(key KType, value VType) bool) { 143 s.sm.Range(func(k, v interface{}) bool { 144 return f(k.(KType), v.(VType)) 145 }) 146 } 147 148 // RangeDeterministic 按照 key 的顺序遍历映射中的 key-value 对,对每个 key-value 对执行给定的函数 f, f返回false则中断退出 149 // 参数 sortableGetter 接收一个 KType 切片并返回一个可排序接口,用于对key进行排序 150 func (s *SyncMap) RangeDeterministic(f func(key KType, value VType) bool, sortableGetter func([]KType) sort.Interface) { 151 var keys []KType 152 s.sm.Range(func(key, value interface{}) bool { 153 keys = append(keys, key.(KType)) 154 return true 155 }) 156 sort.Sort(sortableGetter(keys)) 157 for _, k := range keys { 158 if v, ok := s.Load(k); ok { 159 if !f(k, v) { 160 break 161 } 162 } 163 } 164 }