commit
c319e788e7
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue