package cache import ( "errors" "github.com/vmihailenco/msgpack/v4" "net" "net/url" "strconv" "strings" "time" ) const ( Memcache = "memcache" Redis = "redis" Memory = "memory" Lru = "lru" ) var ( ErrInvalidDriver = errors.New("invalid driver") ) type CacheInterface interface { Has(key string) bool Get(key string, dst ...interface{}) ([]byte, error) Set(key string, val interface{}, ttl time.Duration) (err error) Del(key string) error } func New(uri string) (CacheInterface, error) { u, err := url.Parse(uri) if err != nil { return nil, err } query := u.Query() switch u.Scheme { case Redis: port := u.Port() if port == "" { port = "6379" } return NewRedisCache(RedisSettings{ Address: net.JoinHostPort(u.Hostname(), port), Password: query.Get("password"), }) case Memcache: return NewMemcacheCache(MemcacheSettings{ Servers: strings.Split(u.Host, ","), }) case Memory: cleanupTime := query.Get("cleanupTime") if cleanupTime == "" { cleanupTime = "30" } i, err := strconv.Atoi(cleanupTime) if err != nil { return nil, err } return NewMemoryCache(time.Duration(i) * time.Second) case Lru: size := query.Get("size") if size == "" { size = "128" } i, err := strconv.Atoi(size) if err != nil { return nil, err } return NewLruCache(i) } return nil, ErrInvalidDriver } func encodeValue(val interface{}) ([]byte, error) { var v []byte if b, ok := val.([]byte); ok { v = b } else if s, ok := val.(string); ok { b = []byte(s) } else { b, err := msgpack.Marshal(val) if err != nil { return nil, err } v = b } return v, nil } func decodeDst(b []byte, v interface{}) ([]byte, error) { switch v := v.(type) { case *[]byte: if v != nil { *v = b return b, nil } case *string: if v != nil { *v = string(b) return b, nil } } err := msgpack.Unmarshal(b, v) if err != nil { return nil, err } return b, nil }