package cache import ( "context" "encoding/json" "errors" "sync" "time" ) type encoded_value interface { MarshalBinary() ([]byte, error) } type decoded_value interface { UnmarshalBinary(bs []byte) error } type Scanner interface { Scan(model any) error } type scan struct { err error bs []byte } func newScan(bs []byte, err error) *scan { return &scan{bs: bs, err: err} } func (s *scan) Scan(model any) error { if s.err != nil { return s.err } return unmarshaler(s.bs, model) } type Cache interface { Get(ctx context.Context, key string) ([]byte, error) Gets(ctx context.Context, keys ...string) ([][]byte, error) GetScan(ctx context.Context, key string) Scanner GetEx(ctx context.Context, key string, duration time.Duration) ([]byte, error) GetExScan(ctx context.Context, key string, duration time.Duration) Scanner // Set value 会被序列化, 优先使用 MarshalBinary 方法, 没有则执行 json.Marshal Set(ctx context.Context, key string, value any) error Sets(ctx context.Context, vm map[string]any) error // SetEx value 会被序列化, 优先使用 MarshalBinary 方法, 没有则执行 json.Marshal SetEx(ctx context.Context, key string, value any, duration time.Duration) error Del(ctx context.Context, keys ...string) error GetDel(ctx context.Context, key string) ([]byte, error) GetDelScan(ctx context.Context, key string) Scanner Close() } var ( lock = &sync.Mutex{} marshaler func(data any) ([]byte, error) = json.Marshal unmarshaler func(data []byte, model any) error = json.Unmarshal ErrorKeyNotFound = errors.New("key not found") Default Cache ) func handleValue(value any) ([]byte, error) { var ( bs []byte err error ) switch value.(type) { case []byte: return value.([]byte), nil } if imp, ok := value.(encoded_value); ok { bs, err = imp.MarshalBinary() } else { bs, err = marshaler(value) } return bs, err } func SetMarshaler(fn func(data any) ([]byte, error)) { lock.Lock() defer lock.Unlock() marshaler = fn } func SetUnmarshaler(fn func(data []byte, model any) error) { lock.Lock() defer lock.Unlock() unmarshaler = fn }