package hw04_lru_cache //nolint:golint,stylecheck import ( "log" "sync" ) type Key string type Cache interface { Set(key Key, value interface{}) bool // Добавить значение в кэш по ключу Get(key Key) (interface{}, bool) // Получить значение из кэша по ключу Clear() // Очистить кэш } type lruCache struct { capacity int queue *List items map[Key]*ListItem mx sync.RWMutex } type Item struct { Key Key Value interface{} } func NewCache(capacity int) Cache { return &lruCache{ capacity: capacity, queue: NewList(), items: make(map[Key]*ListItem), } } func (l *lruCache) Set(key Key, value interface{}) bool { if _, exists := l.items[key]; exists { l.mx.RLock() l.items[key].Value = Item{Value: value, Key: key} l.queue.MoveToFront(l.items[key]) l.mx.RUnlock() return exists } if l.queue.Len() == l.capacity { l.mx.RLock() k, ok := l.queue.Back().Value.(Item) if !ok { log.Fatal("Ошибка приведения типов") } delete(l.items, k.Key) l.queue.Remove(l.queue.Back()) l.mx.RUnlock() } l.mx.RLock() l.items[key] = l.queue.PushFront(Item{Value: value, Key: key}) l.mx.RUnlock() return false } func (l *lruCache) Get(key Key) (interface{}, bool) { l.mx.Lock() defer l.mx.Unlock() if l.items[key] == nil { return nil, false } l.queue.MoveToFront(l.items[key]) s, ok := l.items[key].Value.(Item) if !ok { log.Fatal("Ошибка приведения типов") } return s.Value, true } func (l *lruCache) Clear() { l.mx.Lock() l.items = nil l.queue.len = 0 l.queue.Info = ListItem{} l.mx.Unlock() }