package store import ( "sync" ) type CallCreate func(key any) (value any, created bool) type CallCreateMulti func(key any) (m map[any]any, created bool) type CallCheck func(key, value any, exists bool) (rKey, rValue any, created bool) func FromMap(m map[any]any) *Store { return &Store{ locker: new(sync.RWMutex), items: m, } } func New() *Store { return &Store{ locker: new(sync.RWMutex), items: make(map[any]any), } } type Store struct { locker *sync.RWMutex items map[any]any } func (s *Store) delete(key any) (any, bool) { item, check := s.items[key] delete(s.items, key) return item, check } func (s *Store) Delete(key any) (any, bool) { s.locker.Lock() item, check := s.delete(key) s.locker.Unlock() return item, check } func (s *Store) DeleteMulti(keys []any) { s.locker.Lock() for _, key := range keys { delete(s.items, key) } s.locker.Unlock() } func (s *Store) set(key, val any) { s.items[key] = val } func (s *Store) setMulti(m map[any]any) { for key, val := range m { s.items[key] = val } } func (s *Store) Set(key, val any) { s.locker.Lock() s.set(key, val) s.locker.Unlock() } func (s *Store) SetMulti(m map[any]any) { s.locker.Lock() s.setMulti(m) s.locker.Unlock() } func (s *Store) get(key any) (val any, check bool) { val, check = s.items[key] return } func (s *Store) Get(key any) (val any, check bool) { s.locker.RLock() val, check = s.get(key) s.locker.RUnlock() return } func (s *Store) GetCreate(key any, mCreate CallCreate) (res any, check bool) { if res, check = s.Get(key); !check { s.locker.Lock() if res, check = s.get(key); check { s.locker.Unlock() return } if res, check = mCreate(key); check { s.set(key, res) } s.locker.Unlock() } return } func (s *Store) GetCreateMulti(key any, mCreateMulti CallCreateMulti) (res any, check bool) { if res, check = s.Get(key); !check { s.locker.Lock() if res, check = s.get(key); check { s.locker.Unlock() return } var m map[any]any if m, check = mCreateMulti(key); check { s.setMulti(m) res, check = s.items[key] } s.locker.Unlock() } return } func (s *Store) GetCheck(key any, mCheck CallCheck) (res any, check bool) { s.locker.Lock() res, check = s.get(key) if rKey, rVal, rCheck := mCheck(key, res, check); rCheck { s.set(rKey, rVal) key, res, check = rKey, rVal, true } s.locker.Unlock() return } // Each implements a map bypass for each key using the callback function. If the callback function returns false, then the cycle stops func (s *Store) Each(callback func(any, any) bool) { s.locker.RLock() for key, val := range s.items { if !callback(key, val) { s.locker.RUnlock() return } } s.locker.RUnlock() } func (s *Store) Len() (res int) { s.locker.RLock() res = len(s.items) s.locker.RUnlock() return } func (s *Store) Keys() (res []any) { s.locker.RLock() res = make([]any, 0, len(s.items)) for key := range s.items { res = append(res, key) } s.locker.RUnlock() return } func (s *Store) Clear() { s.locker.Lock() s.items = make(map[any]any) s.locker.Unlock() } func (s *Store) Map() (res map[any]any) { res = make(map[any]any) s.locker.RLock() for key, val := range s.items { res[key] = val } s.locker.RUnlock() return }