package cache import ( "errors" "github.com/patrickmn/go-cache" "reflect" "time" ) var ( ErrMemoryCacheNotExists = errors.New("item does not exist") ErrMemoryCacheNotSupported = errors.New("memory cache does not support retrieving items without a destination pointer") ) type MemoryCache struct { c *cache.Cache } func NewMemoryCache(cleanupTime time.Duration) (CacheInterface, error) { c := cache.New(1*time.Minute, cleanupTime) return &MemoryCache{c: c}, nil } func (mc *MemoryCache) Has(key string) bool { _, exists := mc.c.Get(key) return exists } func (mc *MemoryCache) Get(key string, dst ...interface{}) ([]byte, error) { item, exists := mc.c.Get(key) if !exists { return nil, ErrMemoryCacheNotExists } if len(dst) == 0 { return nil, ErrMemoryCacheNotSupported } v := dst[0] switch v := v.(type) { case *string: if v != nil { *v = item.(string) return nil, nil } case *[]byte: if v != nil { *v = item.([]byte) return nil, nil } case *int: if v != nil { *v = item.(int) return nil, nil } case *int8: if v != nil { *v = item.(int8) return nil, nil } case *int16: if v != nil { *v = item.(int16) return nil, nil } case *int32: if v != nil { *v = item.(int32) return nil, nil } case *int64: if v != nil { *v = item.(int64) return nil, nil } case *uint: if v != nil { *v = item.(uint) return nil, nil } case *uint8: if v != nil { *v = item.(uint8) return nil, nil } case *uint16: if v != nil { *v = item.(uint16) return nil, nil } case *uint32: if v != nil { *v = item.(uint32) return nil, nil } case *uint64: if v != nil { *v = item.(uint64) return nil, nil } case *bool: if v != nil { *v = item.(bool) return nil, nil } case *float32: if v != nil { *v = item.(float32) return nil, nil } case *float64: if v != nil { *v = item.(float64) return nil, nil } case *[]string: *v = item.([]string) return nil, nil case *map[string]string: *v = item.(map[string]string) return nil, nil case *map[string]interface{}: *v = item.(map[string]interface{}) return nil, nil case *time.Duration: if v != nil { *v = item.(time.Duration) return nil, nil } case *time.Time: if v != nil { *v = item.(time.Time) return nil, nil } } vv := reflect.ValueOf(dst[0]) if !vv.IsValid() { return nil, errors.New("dst pointer is not valid") } if vv.Kind() != reflect.Ptr { return nil, errors.New("dst pointer is not a pointer") } vv = vv.Elem() if !vv.IsValid() { return nil, errors.New("dst pointer is not a valid element") } vv.Set(reflect.ValueOf(item)) return nil, nil } func (mc *MemoryCache) Set(key string, val interface{}, ttl time.Duration) error { mc.c.Set(key, val, ttl) return nil } func (mc *MemoryCache) Del(key string) error { mc.c.Delete(key) return nil }