From c319e788e707c136238e99d0fd32c491536d826d Mon Sep 17 00:00:00 2001 From: serr Date: Thu, 2 Jan 2025 23:30:51 +0300 Subject: [PATCH] start work --- simplecache.go | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 simplecache.go diff --git a/simplecache.go b/simplecache.go new file mode 100644 index 0000000..300a0ca --- /dev/null +++ b/simplecache.go @@ -0,0 +1,132 @@ +package simplecache + +import ( + "errors" + "fmt" + "sync" + "time" +) + +// Элемент в кэше - это данные и время их жизни. +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) Print() { + c.RLock() + defer c.RUnlock() + + for key, item := range c.storage { + fmt.Printf("Key: %s, DestroyTimestamp: %d\n", key, item.destroyTimestamp) + } +}