This commit is contained in:
2024-12-18 03:41:30 +08:00
commit 8798223f68
45 changed files with 3020 additions and 0 deletions

23
myRedis/Ierator.go Normal file
View File

@ -0,0 +1,23 @@
package myRedis
type Iterator struct {
data []interface{}
index int
}
func NewIterator(data []interface{}) *Iterator {
return &Iterator{data: data}
}
func (t *Iterator) HasNext() bool {
if t.data == nil || len(t.data) == 0 {
return false
}
return t.index < len(t.data)
}
func (t *Iterator) Next() (ret interface{}) {
ret = t.data[t.index]
t.index = t.index + 1
return
}

33
myRedis/IntResult.go Normal file
View File

@ -0,0 +1,33 @@
package myRedis
type IntResult struct {
Result int64
Err error
}
func NewIntResult(result int64, err error) *IntResult {
return &IntResult{Result: result, Err: err}
}
func (t *IntResult) Unwrap() int64 {
if t.Err != nil {
panic(t.Err)
}
return t.Result
}
func (t *IntResult) UnwrapOr(str int64) int64 {
if t.Err != nil {
return str
} else {
return t.Result
}
}
func (t *IntResult) UnwrapOrElse(f func() int64) int64 {
if t.Err != nil {
return f()
}
return t.Result
}

View File

@ -0,0 +1,25 @@
package myRedis
type InterfaceResult struct {
Result interface{}
Err error
}
func NewInterfaceResult(result interface{}, err error) *InterfaceResult {
return &InterfaceResult{Result: result, Err: err}
}
func (t *InterfaceResult) Unwrap() interface{} {
if t.Err != nil {
panic(t.Err)
}
return t.Result
}
func (t *InterfaceResult) UnwrapOr(a interface{}) interface{} {
if t.Err != nil {
return a
}
return t.Result
}

52
myRedis/OperationAttr.go Normal file
View File

@ -0,0 +1,52 @@
package myRedis
import (
"fmt"
"time"
)
const (
AttrExpr = "expr"
AttrNx = "nx"
AttrXx = "xx"
)
type empty struct {
}
type OperationAttr struct {
Name string
Value interface{}
}
type OperationAttrs []*OperationAttr
func (t OperationAttrs) Find(name string) *InterfaceResult {
for _, attr := range t {
if attr.Name == name {
return NewInterfaceResult(attr.Value, nil)
}
}
return NewInterfaceResult(nil, fmt.Errorf("OperationAttrs found error:%s", name))
}
func WithExpire(t time.Duration) *OperationAttr {
return &OperationAttr{
Name: AttrExpr,
Value: t,
}
}
func WithNX() *OperationAttr {
return &OperationAttr{
Name: AttrNx,
Value: empty{},
}
}
func WithXX() *OperationAttr {
return &OperationAttr{
Name: AttrXx,
Value: empty{},
}
}

132
myRedis/SimpleCache.go Normal file
View File

@ -0,0 +1,132 @@
package myRedis
import (
"bytes"
"encoding/gob"
"encoding/json"
"time"
)
const (
SerializerNot = ""
SerializerJson = "json"
SerializerGob = "gob"
)
type CacheGetterFunc func() interface{}
type SimpleCache struct {
Operation *StringOperation
Expire time.Duration
CacheGetter CacheGetterFunc
Serializer string //序列化方式
}
func NewSimpleCache(operation *StringOperation, expire time.Duration, serializer string) *SimpleCache {
return &SimpleCache{Operation: operation, Expire: expire, Serializer: serializer}
}
func (t *SimpleCache) SetCacheGetterFunc(f CacheGetterFunc) *SimpleCache {
t.CacheGetter = f
return t
}
// 设置缓存
func (t *SimpleCache) SetCache(key string, value interface{}) {
//if t.Serializer == SerializerNot {
//}
if t.Serializer == SerializerJson {
f := func() string {
j, e := json.Marshal(value)
if e != nil {
return e.Error()
} else {
return string(j)
}
}
t.Operation.Set(key, f(), WithExpire(t.Expire)).Unwrap()
} else if t.Serializer == SerializerGob {
f := func() string {
var buf = &bytes.Buffer{}
enc := gob.NewEncoder(buf)
if err := enc.Encode(value); err != nil {
return ""
}
return buf.String()
}
t.Operation.Set(key, f(), WithExpire(t.Expire)).Unwrap()
} else {
t.Operation.Set(key, value, WithExpire(t.Expire)).Unwrap()
}
}
func (t *SimpleCache) GetCache(key string) (ret interface{}) {
//如果没有设置的话
if t.CacheGetter == nil {
panic("没有设置CacheGetter")
}
if t.Serializer == SerializerNot {
}
if t.Serializer == SerializerJson {
f := func() string {
j, e := json.Marshal(t.CacheGetter())
if e != nil {
return e.Error()
} else {
return string(j)
}
}
ret = t.Operation.Get(key).UnwrapOrElse(func() string {
data := f()
t.Operation.Set(key, data, WithExpire(t.Expire)).Unwrap()
return data
})
}
if t.Serializer == SerializerGob {
f := func() string {
var buf = &bytes.Buffer{}
enc := gob.NewEncoder(buf)
if err := enc.Encode(t.CacheGetter()); err != nil {
return ""
}
return buf.String()
}
ret = t.Operation.Get(key).UnwrapOrElse(func() string {
data := f()
t.Operation.Set(key, data, WithExpire(t.Expire)).Unwrap()
return data
})
}
return
}
func (t *SimpleCache) DelCache(key string) int64 {
return t.Operation.Del(key).UnwrapOr(0)
}
func (t *SimpleCache) GetCacheForObject(key string, obj interface{}) interface{} {
ret := t.GetCache(key)
if ret == nil {
return nil
}
if t.Serializer == SerializerNot {
obj = ret
} else if t.Serializer == SerializerJson {
err := json.Unmarshal([]byte(ret.(string)), obj)
if err != nil {
return nil
}
} else if t.Serializer == SerializerGob {
var buf = &bytes.Buffer{}
buf.WriteString(ret.(string))
dec := gob.NewDecoder(buf)
if dec.Decode(obj) != nil {
return nil
}
}
return nil
}

29
myRedis/SliceResult.go Normal file
View File

@ -0,0 +1,29 @@
package myRedis
type SliceResult struct {
Result []interface{}
Err error
}
func NewSliceResult(result []interface{}, err error) *SliceResult {
return &SliceResult{Result: result, Err: err}
}
func (t *SliceResult) Unwrap() []interface{} {
if t.Err != nil {
panic(t.Err)
}
return t.Result
}
func (t *SliceResult) UnwrapOr(strs []interface{}) []interface{} {
if t.Err != nil {
return strs
} else {
return t.Result
}
}
func (t *SliceResult) Iter() *Iterator {
return NewIterator(t.Result)
}

52
myRedis/StringCache.go Normal file
View File

@ -0,0 +1,52 @@
package myRedis
import (
"github.com/redis/go-redis/v9"
"time"
)
type StringCache struct {
Operation *StringOperation
Expire time.Duration
DefaultString string
}
func NewStringCache(redisClient *redis.Client) *StringCache {
return &StringCache{
Operation: NewStringOperation(redisClient),
Expire: time.Second * 0,
DefaultString: "",
}
}
func (t *StringCache) SetExpire(expire time.Duration) *StringCache {
t.Expire = expire
return t
}
func (t *StringCache) SetDefaultString(defaultString string) *StringCache {
t.DefaultString = defaultString
return t
}
func (t *StringCache) SetCache(key string, value string) {
t.Operation.Set(key, value, WithExpire(t.Expire))
}
func (t *StringCache) GetCache(key string) (ret string) {
ret = t.Operation.Get(key).UnwrapOrElse(func() string {
if t.DefaultString != "" {
t.SetCache(key, t.DefaultString)
}
return t.DefaultString
})
return
}
func (t *StringCache) IsExist(key string) bool {
return t.Operation.Exist(key).UnwrapOr(0) != 0
}
func (t *StringCache) DelCache(key string) int64 {
return t.Operation.Del(key).UnwrapOr(0)
}

View File

@ -0,0 +1,48 @@
package myRedis
import (
"context"
"github.com/redis/go-redis/v9"
"time"
)
type StringOperation struct {
ctx context.Context
client *redis.Client
}
func NewStringOperation(client *redis.Client) *StringOperation {
return &StringOperation{ctx: context.Background(), client: client}
}
func (t *StringOperation) Set(key string, value interface{}, attrs ...*OperationAttr) *InterfaceResult {
exp := OperationAttrs(attrs).Find(AttrExpr).UnwrapOr(0 * time.Second).(time.Duration)
nx := OperationAttrs(attrs).Find(AttrNx).UnwrapOr(nil)
if nx != nil {
return NewInterfaceResult(t.client.SetNX(t.ctx, key, value, exp).Result())
}
xx := OperationAttrs(attrs).Find(AttrXx).UnwrapOr(nil)
if xx != nil {
return NewInterfaceResult(t.client.SetXX(t.ctx, key, value, exp).Result())
}
return NewInterfaceResult(t.client.Set(t.ctx, key, value, exp).Result())
}
func (t *StringOperation) Get(key string) *StringResult {
return NewStringResult(t.client.Get(t.ctx, key).Result())
}
func (t *StringOperation) MGet(key ...string) *SliceResult {
return NewSliceResult(t.client.MGet(t.ctx, key...).Result())
}
func (t *StringOperation) Del(key string) *IntResult {
return NewIntResult(t.client.Del(t.ctx, key).Result())
}
func (t *StringOperation) Exist(key string) *IntResult {
return NewIntResult(t.client.Exists(t.ctx, key).Result())
}

33
myRedis/StringResult.go Normal file
View File

@ -0,0 +1,33 @@
package myRedis
type StringResult struct {
Result string
Err error
}
func NewStringResult(result string, err error) *StringResult {
return &StringResult{Result: result, Err: err}
}
func (t *StringResult) Unwrap() string {
if t.Err != nil {
panic(t.Err)
}
return t.Result
}
func (t *StringResult) UnwrapOr(str string) string {
if t.Err != nil {
return str
} else {
return t.Result
}
}
func (t *StringResult) UnwrapOrElse(f func() string) string {
if t.Err != nil {
return f()
}
return t.Result
}

33
myRedis/cli.go Normal file
View File

@ -0,0 +1,33 @@
package myRedis
import (
"github.com/redis/go-redis/v9"
"time"
)
type Client struct {
client *redis.Client
}
func NewClient(client *redis.Client) *Client {
if client == nil {
panic("redis client is nil")
}
return &Client{client: client}
}
func (t *Client) GetClient() *redis.Client {
return t.client
}
func (t *Client) NewStringCache() *StringCache {
return NewStringCache(t.client)
}
func (t *Client) NewJsonCache(expire time.Duration) *SimpleCache {
return NewSimpleCache(NewStringOperation(t.client), expire, SerializerJson)
}
func (t *Client) NewGobCache(expire time.Duration) *SimpleCache {
return NewSimpleCache(NewStringOperation(t.client), expire, SerializerGob)
}

60
myRedis/index.go Normal file
View File

@ -0,0 +1,60 @@
package myRedis
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
"log"
"sync"
)
type SimpleRedis struct {
Host string
Password string
hosts map[int]*Hosts
}
type Hosts struct {
clientOnce sync.Once
client *redis.Client
}
func NewSimpleRedis(host string, password string) *SimpleRedis {
return &SimpleRedis{Host: host, Password: password, hosts: map[int]*Hosts{}}
}
func (t *SimpleRedis) connectRedis(index int) *redis.Client {
if t.hosts[index] == nil {
t.hosts[index] = &Hosts{
clientOnce: sync.Once{},
client: nil,
}
}
t.hosts[index].clientOnce.Do(func() {
redisClient := redis.NewClient(&redis.Options{
Addr: t.Host,
Password: t.Password, // no password set
DB: index, // use default DB
//连接池容量以闲置链接数量
PoolSize: 15,
MinIdleConns: 10,
})
pong, err := redisClient.Ping(context.Background()).Result()
if err != nil {
panic(fmt.Errorf("connect error:%s", err))
}
log.Println(fmt.Sprintf("redis newClient success, index%d, pong: %s", index, pong))
t.hosts[index].client = redisClient
})
return t.hosts[index].client
}
func (t *SimpleRedis) ConnectDefaultRedis() *Client {
return t.GetRedisClient(0)
}
func (t *SimpleRedis) GetRedisClient(index int) *Client {
return NewClient(t.connectRedis(index))
}