package redis import ( "context" "github.com/pkg/errors" "github.com/redis/go-redis/v9" "strings" "time" ) const ( keyPrefix = "baize::cache::" ) type Cache struct { namespace string redisClient *redis.Client } func New(address string, userName string, password string, db int, namespace string) (*Cache, error) { if address == "" { return nil, errors.New("redis address不能为空") } return &Cache{ namespace: namespace, redisClient: redis.NewClient(&redis.Options{ Addr: address, Username: userName, Password: password, DB: db, })}, nil } func Destroy(cache *Cache) error { if cache == nil || cache.redisClient == nil { return nil } err := cache.redisClient.Close() if err != nil { return errors.New(err.Error()) } cache.redisClient = nil return nil } func (cache *Cache) Set(key string, value string, expireSec int64) error { cmd := cache.redisClient.Set(context.Background(), cache.key2CacheKey(key), value, time.Duration(expireSec)*time.Second) if cmd.Err() != nil { return errors.New(cmd.Err().Error()) } return nil } func (cache *Cache) Get(key string) (string, error) { cmd := cache.redisClient.Get(context.Background(), cache.key2CacheKey(key)) if cmd.Err() != nil { if cmd.Err().Error() == redis.Nil.Error() { return "", nil } return "", errors.New(cmd.Err().Error()) } return cmd.Val(), nil } func (cache *Cache) GetMulti(keys []string) (map[string]string, error) { result := make(map[string]string) for _, key := range keys { cmd := cache.redisClient.Get(context.Background(), cache.key2CacheKey(key)) if cmd.Err() != nil { if cmd.Err().Error() == redis.Nil.Error() { result[key] = "" continue } return nil, cmd.Err() } result[key] = cmd.Val() } return result, nil } func (cache *Cache) GetAll() (map[string]string, error) { result := make(map[string]string) keysCmd := cache.redisClient.Keys(context.Background(), keyPrefix+cache.namespace+"::*") if keysCmd.Err() != nil { return nil, errors.New(keysCmd.Err().Error()) } for _, cacheKey := range keysCmd.Val() { cmd := cache.redisClient.Get(context.Background(), cacheKey) if cmd.Err() != nil { if cmd.Err().Error() == redis.Nil.Error() { result[cache.cacheKey2Key(cacheKey)] = "" continue } return nil, cmd.Err() } result[cache.cacheKey2Key(cacheKey)] = cmd.Val() } return result, nil } func (cache *Cache) Delete(key string) error { cmd := cache.redisClient.Del(context.Background(), cache.key2CacheKey(key)) if cmd.Err() != nil { return errors.New(cmd.Err().Error()) } return nil } func (cache *Cache) Clear() error { keysCmd := cache.redisClient.Keys(context.Background(), keyPrefix+cache.namespace+"::*") if keysCmd.Err() != nil { return errors.New(keysCmd.Err().Error()) } if keysCmd.Val() == nil || len(keysCmd.Val()) == 0 { return nil } delCmd := cache.redisClient.Del(context.Background(), keysCmd.Val()...) if delCmd.Err() != nil { return errors.New(delCmd.Err().Error()) } return nil } func (cache *Cache) key2CacheKey(key string) string { return keyPrefix + cache.namespace + "::" + key } func (cache *Cache) cacheKey2Key(cacheKey string) string { return strings.TrimPrefix(cacheKey, keyPrefix+cache.namespace+"::") }