package simplecache import ( "errors" "sync" "time" ) // Структура виде ключ-значение для возвращения списка элементов кэша с их ключами. type KeyItemPair struct { Key string Item Item } // Элемент в кэше - это данные и время их жизни. type Item struct { destroyTimestamp int64 // Момент в Unix-секундах, когда элемент становится устаревшим data interface{} // Данные } // Кэш - это хранилище элементов и инервал его очистки (ну и мьютекс на всякий случай). // Интервал очистки хранилища укахывается в НАНОСЕКУНДАХ (используй множители для преобразования во что-то другое). type Cache struct { sync.RWMutex // Мьютекс ждя реализации безопасного доступа к общим данным storage map[string]Item // Хранилище элементов cleanupInterval time.Duration // Интервал очистки хранилища в наносекундах } // NewCache создает новый экземпляр Cache с интервалом очистки cleanupInterval. // Если cleanupInterval < 0, то кэш не будет очищаться автоматически. func NewCache(cleanupInterval time.Duration) *Cache { cache := &Cache{ storage: make(map[string]Item), cleanupInterval: cleanupInterval, } // Запускаем Garbage Collector если интервал очистки больше 0 // Иначе (если он отрицательный) кэш будет жить до ручного вызова Cleanup if cleanupInterval > 0 { go cache.gc(cleanupInterval) } return cache } // gc = Garbage Collector. func (c *Cache) gc(cleanupInterval time.Duration) { ticker := time.NewTicker(cleanupInterval) defer ticker.Stop() for range ticker.C { c.Cleanup() } } // Перебирает все элементы в кэше, удаляет устаревшие. func (c *Cache) Cleanup() { c.Lock() defer c.Unlock() for key, item := range c.storage { if item.destroyTimestamp <= time.Now().Unix() { delete(c.storage, key) } } } // Удаление всех элементов из кэша. func (c *Cache) Flush() { c.Lock() defer c.Unlock() for key := range c.storage { delete(c.storage, key) } } // Получение элемента из кэша по ключу. func (c *Cache) Get(key string) (interface{}, bool) { c.RLock() defer c.RUnlock() item, found := c.storage[key] // Элемент не найден в кэше if !found { return nil, false } return item.data, true } // Удаление элемента по ключу. func (c *Cache) Delete(key string) error { c.Lock() defer c.Unlock() if _, found := c.storage[key]; !found { return errors.New("key not found") } delete(c.storage, key) return nil } // Добавление элемента в кэш. // key - ключ. // data - данные. // ttl - время жизни элемента (time to life) в наносекундах. func (c *Cache) Add(key string, data interface{}, ttl time.Duration) { c.Lock() defer c.Unlock() c.storage[key] = Item{ destroyTimestamp: time.Now().Unix() + int64(ttl.Seconds()), data: data, } } // Вернет количество элементов в кэше. func (c *Cache) Count() int { c.RLock() defer c.RUnlock() return len(c.storage) } // Печать всех элементов кэша (ключ и время уничтожения). func (c *Cache) List() []KeyItemPair { c.RLock() defer c.RUnlock() // Создаем срез для хранения пар ключ-значение items := make([]KeyItemPair, 0, len(c.storage)) // Заполняем срез парами ключ-значение for key, item := range c.storage { items = append(items, KeyItemPair{Key: key, Item: item}) } return items } // Возвращает данные элемента кэша. func (i *Item) Data() interface{} { return i.data } // Возвращает момент смерти элемента кэша. func (i *Item) DestroyTimestamp() int64 { return i.destroyTimestamp }