Back to questions
Senior
4
type TTLCache interface { Set(k string, v any, ttl time.Duration) Get(k string) (any, bool) Del(k string) bool } // Не должно утекать по памяти // гет не должен отдавать просрочку //реализация
Companies where asked
X5
Answer from AI
sobes.tech AI
Для реализации TTLCache в Go, который не допускает утечек памяти и не возвращает просроченные значения, можно использовать структуру с мьютексом для потокобезопасности, карту для хранения значений и время истечения для каждого ключа. Также нужен механизм очистки просроченных элементов, например, через периодический горутин.
Пример реализации:
package ttlcache
import (
"sync"
"time"
)
type cacheItem struct {
value any
expiration int64 // unix nano timestamp
}
type TTLCache interface {
Set(k string, v any, ttl time.Duration)
Get(k string) (any, bool)
Del(k string) bool
}
type ttlCache struct {
mu sync.RWMutex
items map[string]cacheItem
quit chan struct{}
}
func NewTTLCache(cleanupInterval time.Duration) TTLCache {
c := &ttlCache{
items: make(map[string]cacheItem),
quit: make(chan struct{}),
}
go c.cleanupLoop(cleanupInterval)
return c
}
func (c *ttlCache) Set(k string, v any, ttl time.Duration) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[k] = cacheItem{
value: v,
expiration: time.Now().Add(ttl).UnixNano(),
}
}
func (c *ttlCache) Get(k string) (any, bool) {
c.mu.RLock()
item, found := c.items[k]
c.mu.RUnlock()
if !found {
return nil, false
}
if time.Now().UnixNano() > item.expiration {
// элемент просрочен, удаляем
c.mu.Lock()
delete(c.items, k)
c.mu.Unlock()
return nil, false
}
return item.value, true
}
func (c *ttlCache) Del(k string) bool {
c.mu.Lock()
defer c.mu.Unlock()
if _, found := c.items[k]; found {
delete(c.items, k)
return true
}
return false
}
func (c *ttlCache) cleanupLoop(interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
now := time.Now().UnixNano()
c.mu.Lock()
for k, item := range c.items {
if now > item.expiration {
delete(c.items, k)
}
}
c.mu.Unlock()
case <-c.quit:
return
}
}
}
func (c *ttlCache) Close() {
close(c.quit)
}
В этой реализации:
- При Set сохраняется значение с временем истечения.
- При Get проверяется срок годности, если просрочено — удаляется и возвращается false.
- Есть горутина, которая периодически очищает просроченные записи, чтобы не было утечек памяти.
- Используется RWMutex для потокобезопасности.