/
gus
/
caches
Обзор
Документация
Войти
/
gus
/
caches
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
cache/cache.go
185 строк
4 KB
da.guselnikov
refactoring
06 май 2024, 03:49
06 май 2024, 03:49
4199b8d
Код
Авторство
О чём код?
package cache import ( "sync" "time" ) type item[V any] struct { Value V Created time.Time Expiration int64 } // Cache хранилище данных в памяти. type Cache[K comparable, V any] struct { mutex sync.RWMutex items map[K]item[V] defaultExpiration time.Duration cleanupInterval time.Duration } // NewCache инициализирует новый кеш в памяти. func NewCache[K comparable, V any](defaultExpiration, cleanupInterval time.Duration) *Cache[K, V] { cache := Cache[K, V]{ defaultExpiration: defaultExpiration, cleanupInterval: cleanupInterval, items: make(map[K]item[V]), } if cleanupInterval > 0 { go cache.cleanup() } return &cache } func (c *Cache[K, V]) set(key K, value V, duration time.Duration) { if duration == 0 { duration = c.defaultExpiration } var expiration int64 if duration > 0 { expiration = time.Now().Add(duration).UnixNano() } c.items[key] = item[V]{ Value: value, Expiration: expiration, Created: time.Now(), } } // Set устанавливает значение. func (c *Cache[K, V]) Set(key K, value V, duration time.Duration) { c.mutex.Lock() defer c.mutex.Unlock() c.set(key, value, duration) } func (c *Cache[K, V]) get(key K) (V, bool) { item, found := c.items[key] if !found { return *new(V), false } if item.Expiration > 0 { if time.Now().UnixNano() > item.Expiration { return *new(V), false } } return item.Value, true } // Get получает значение. func (c *Cache[K, V]) Get(key K) (V, bool) { c.mutex.RLock() defer c.mutex.RUnlock() return c.get(key) } // Delete удаляет значение. func (c *Cache[K, V]) Delete(key K) { c.mutex.Lock() defer c.mutex.Unlock() delete(c.items, key) } // GetAndDelete получает значение и удаляет его из списка. func (c *Cache[K, V]) GetAndDelete(key K) (V, bool) { c.mutex.Lock() item, found := c.get(key) delete(c.items, key) c.mutex.Unlock() return item, found } // Exists проверяет, существует ли ключ. func (c *Cache[K, V]) Exists(key K) bool { c.mutex.RLock() defer c.mutex.RUnlock() _, found := c.items[key] return found } // Clear очищает кеш. func (c *Cache[K, V]) Clear() { c.mutex.Lock() defer c.mutex.Unlock() clear(c.items) } // Count количество данных в карте. func (c *Cache[K, V]) Count() int { c.mutex.RLock() defer c.mutex.RUnlock() return len(c.items) } // Append добавляет карту к кешу. func (c *Cache[K, V]) Append(list map[K]V) int { c.mutex.Lock() defer c.mutex.Unlock() for key, val := range list { c.set(key, val, c.defaultExpiration) } return len(c.items) } // Values возвращает значения в виде массива. func (c *Cache[K, V]) Values() []V { c.mutex.RLock() defer c.mutex.RUnlock() result := make([]V, 0, len(c.items)) for _, item := range c.items { result = append(result, item.Value) } return result } // Keys возвращает ключи в виде массива. func (c *Cache[K, V]) Keys() []K { c.mutex.RLock() defer c.mutex.RUnlock() result := make([]K, 0, len(c.items)) for key := range c.items { result = append(result, key) } return result } func (c *Cache[K, V]) cleanup() { for { <-time.After(c.cleanupInterval) if c.items != nil { c.clearExpiredKeys() } } } // clearExpiredKeys возвращает список "просроченных" ключей func (c *Cache[K, V]) clearExpiredKeys() { c.mutex.Lock() defer c.mutex.Unlock() for key, item := range c.items { if time.Now().UnixNano() > item.Expiration && item.Expiration > 0 { delete(c.items, key) } } }