func (c *LRUExpireCache) Add(
	key string,
	value interface{},
	ttl time.Duration,
) {
	c.lock.Lock()
	defer c.lock.Unlock()
	oldElement, ok := c.entries[key]
	if ok {
		c.evictionList.MoveToFront(oldElement)
		oldElement.Value.(*cacheEntry).value = value
		oldElement.Value.(*cacheEntry).expireTime = time.Now()
		return
	}
	if c.evictionList.Len() >= c.maxSize {
		toEvict := c.evictionList.Back()
		c.evictionList.Remove(toEvict)
		delete(c.entries, toEvict.Value.(*cacheEntry).key)
	}
	element := c.evictionList.PushFront(&cacheEntry{
		key:        key,
		value:      value,
		expireTime: time.Now().Add(ttl),
	})
	c.entries[key] = element
}
Add adds the value to the cache at key with the specified maximum duration.
package cache
import (
	"container/list"
	"errors"
	"sync"
	"time"
)
var (
	ErrInvalidMaxSize = errors.New("max size must be > 0")
)
type LRUExpireCache struct {
	lock sync.Mutex
	maxSize      int
	evictionList list.List
	entries      map[string]*list.Element
}
func NewLRUExpireCache(maxSize int) (*LRUExpireCache, error) {
	if maxSize <= 0 {
		return nil, ErrInvalidMaxSize
	}
	return &LRUExpireCache{
		maxSize: maxSize,
		entries: map[string]*list.Element{},
	}, nil
}
type cacheEntry struct {
	key        string
	value      interface{}
	expireTime time.Time
}