func NewCache(options ...Option) (Cache, error) {
	res := cacheImpl{
		items:     map[string]*list.Element{},
		evictList: list.New(),
		ttl:       noEvictionTTL,
		maxKeys:   0,
	}
	for _, opt := range options {
		if err := opt(&res); err != nil {
			return nil, errors.Wrap(err, "failed to set cache option")
		}
	}
	return &res, nil
}
NewCache returns a new Cache.
Default MaxKeys is unlimited (0).
Default TTL is 10 years, sane value for expirable cache is 5 minutes.
Default eviction mode is LRC, appropriate option allow to change it to LRU.
package cache
import (
	"container/list"
	"fmt"
	"sync"
	"time"
	"github.com/pkg/errors"
)
type Cache interface {
	fmt.Stringer
	Set(key string, value interface{}, ttl time.Duration)
	Get(key string) (interface{}, bool)
	Peek(key string) (interface{}, bool)
	Keys() []string
	Len() int
	Invalidate(key string)
	InvalidateFn(fn func(key string) bool)
	RemoveOldest()
	DeleteExpired()
	Purge()
	Stat() Stats
}
type Stats struct {
	Hits, Misses   int  
	Added, Evicted int  
}
type cacheImpl struct {
	ttl       time.Duration
	maxKeys   int
	isLRU     bool
	onEvicted func(key string, value interface{})
	sync.Mutex
	stat      Stats
	items     map[string]*list.Element
	evictList *list.List
}
const noEvictionTTL = time.Hour * 24 * 365 * 10