上传redis的序列化优化

This commit is contained in:
liwei1dao 2022-07-12 11:03:41 +08:00
parent a2fea3daa9
commit 4f4d0dec0b
30 changed files with 592 additions and 225 deletions

View File

@ -8,6 +8,7 @@ import (
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase"
"go_dreamfactory/lego/sys/codec"
"go_dreamfactory/lego/sys/event"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/sys/rpcx"
@ -84,6 +85,12 @@ func (this *RPCXService) InitSys() {
} else {
log.Infof("Sys event Init success !")
}
//初始化编码Codec
if err := codec.OnInit(this.opts.Setting.Sys["codec"]); err != nil {
log.Panicf(fmt.Sprintf("Sys codec Init err:%v", err))
} else {
log.Infof("Sys codec Init success !")
}
//初始化rpcx系统
if err := rpcx.OnInit(this.opts.Setting.Sys["rpcx"], rpcx.SetServiceTag(this.GetTag()), rpcx.SetServiceId(this.GetId()), rpcx.SetServiceType(this.GetType()), rpcx.SetServiceVersion(this.GetVersion()), rpcx.SetServiceAddr(fmt.Sprintf("%s:%d", this.GetIp(), this.GetPort()))); err != nil {
log.Panicf(fmt.Sprintf("Sys rpcx Init err:%v", err))

View File

@ -1,6 +1,9 @@
package codec
import (
"errors"
"fmt"
"reflect"
"sync"
"go_dreamfactory/lego/sys/codec/core"
@ -136,7 +139,7 @@ func (this *Codec) MarshalJson(val interface{}, option ...core.ExecuteOption) (b
}
//解码json到对象
func (this *Codec) UnmarshalJson(data []byte, v interface{}) error {
func (this *Codec) UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error {
extra := this.BorrowExtractor(data)
defer this.ReturnExtractor(extra)
extra.ReadVal(v)
@ -145,12 +148,92 @@ func (this *Codec) UnmarshalJson(data []byte, v interface{}) error {
//编码对象到mapjson
func (this *Codec) MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error) {
if nil == val {
err = errors.New("val is null")
return
}
cacheKey := reflect2.RTypeOf(val)
encoder := this.GetEncoderFromCache(cacheKey)
if encoder == nil {
typ := reflect2.TypeOf(val)
encoder = this.EncoderOf(typ)
}
if encoderMapJson, ok := encoder.(core.IEncoderMapJson); !ok {
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
} else {
ret, err = encoderMapJson.EncodeToMapJson(reflect2.PtrOf(val))
}
return
}
//解码mapjson到对象
func (this *Codec) UnmarshalMapString(data []byte, v interface{}) error {
return nil
func (this *Codec) UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error) {
cacheKey := reflect2.RTypeOf(val)
decoder := this.GetDecoderFromCache(cacheKey)
if decoder == nil {
typ := reflect2.TypeOf(val)
if typ == nil || typ.Kind() != reflect.Ptr {
err = errors.New("can only unmarshal into pointer")
return
}
decoder = this.DecoderOf(typ)
}
ptr := reflect2.PtrOf(val)
if ptr == nil {
err = errors.New("can not read into nil pointer")
return
}
if decoderMapJson, ok := decoder.(core.IDecoderMapJson); !ok {
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
} else {
err = decoderMapJson.DecodeForMapJson(ptr, data)
}
return
}
//编码对象到sliceJson
func (this *Codec) MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error) {
if nil == val {
err = errors.New("val is null")
return
}
cacheKey := reflect2.RTypeOf(val)
encoder := this.GetEncoderFromCache(cacheKey)
if encoder == nil {
typ := reflect2.TypeOf(val)
encoder = this.EncoderOf(typ)
}
if encoderMapJson, ok := encoder.(core.IEncoderSliceJson); !ok {
err = fmt.Errorf("val type:%T not support MarshalMapJson", val)
} else {
ret, err = encoderMapJson.EncodeToSliceJson(reflect2.PtrOf(val))
}
return
}
//解码sliceJson到对象
func (this *Codec) UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error) {
cacheKey := reflect2.RTypeOf(val)
decoder := this.GetDecoderFromCache(cacheKey)
if decoder == nil {
typ := reflect2.TypeOf(val)
if typ == nil || typ.Kind() != reflect.Ptr {
err = errors.New("can only unmarshal into pointer")
return
}
decoder = this.DecoderOf(typ)
}
ptr := reflect2.PtrOf(val)
if ptr == nil {
err = errors.New("can not read into nil pointer")
return
}
if decoderMapJson, ok := decoder.(core.IDecoderSliceJson); !ok {
err = fmt.Errorf("val type:%T not support UnmarshalSliceJson", val)
} else {
err = decoderMapJson.DecodeForSliceJson(ptr, data)
}
return
}
///日志***********************************************************************

View File

@ -7,7 +7,11 @@ import (
type (
ISys interface {
MarshalJson(v interface{}, option ...core.ExecuteOption) ([]byte, error)
UnmarshalJson(data []byte, v interface{}) error
UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error
MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error)
UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error)
MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error)
UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error)
}
)
@ -22,3 +26,22 @@ func NewSys(option ...core.Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}
func MarshalJson(v interface{}, option ...core.ExecuteOption) ([]byte, error) {
return defsys.MarshalJson(v, option...)
}
func UnmarshalJson(data []byte, v interface{}, option ...core.ExecuteOption) error {
return defsys.UnmarshalJson(data, v, option...)
}
func MarshalMapJson(val interface{}, option ...core.ExecuteOption) (ret map[string]string, err error) {
return defsys.MarshalMapJson(val, option...)
}
func UnmarshalMapJson(data map[string]string, val interface{}, option ...core.ExecuteOption) (err error) {
return defsys.UnmarshalMapJson(data, val, option...)
}
func MarshalSliceJson(val interface{}, option ...core.ExecuteOption) (ret []string, err error) {
return defsys.MarshalSliceJson(val, option...)
}
func UnmarshalSliceJson(data []string, val interface{}, option ...core.ExecuteOption) (err error) {
return defsys.UnmarshalSliceJson(data, val)
}

View File

@ -111,15 +111,32 @@ type (
Error() error
SetErr(err error)
}
//编码器
//Json 编码器
IEncoder interface {
IsEmpty(ptr unsafe.Pointer) bool
Encode(ptr unsafe.Pointer, stream IStream)
}
//解码器
//MapJson 编码器
IEncoderMapJson interface {
EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error)
}
//SliceJson 编码器
IEncoderSliceJson interface {
EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error)
}
//Json 解码器
IDecoder interface {
Decode(ptr unsafe.Pointer, extra IExtractor)
}
//MapJson 解码器
IDecoderMapJson interface {
DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error)
}
//MapJson 解码器
IDecoderSliceJson interface {
DecodeForSliceJson(ptr unsafe.Pointer, extra []string) (err error)
}
//空校验
CheckIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool

View File

@ -113,6 +113,20 @@ func _createDecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
}
}
// string
func BytesToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
func StringToBytes(s string) []byte {
return *(*[]byte)(unsafe.Pointer(
&struct {
string
Cap int
}{s, len(s)},
))
}
//根节点 -------------------------------------------------------------------
type rootDecoder struct {
decoder core.IDecoder
@ -143,12 +157,21 @@ type onePtrEncoder struct {
encoder core.IEncoder
}
func (encoder *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
func (this *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return this.encoder.IsEmpty(unsafe.Pointer(&ptr))
}
func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
func (this *onePtrEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
this.encoder.Encode(unsafe.Pointer(&ptr), stream)
}
func (this *onePtrEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) {
if encoderMapJson, ok := this.encoder.(core.IEncoderMapJson); !ok {
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.encoder)
return
} else {
return encoderMapJson.EncodeToMapJson(ptr)
}
}
//错误节点 ------------------------------------------------------------------

View File

@ -1,6 +1,7 @@
package factory
import (
"errors"
"fmt"
"io"
"unsafe"
@ -13,7 +14,7 @@ import (
func decoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
arrayType := typ.(*reflect2.UnsafeArrayType)
decoder := DecoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem())
return &arrayDecoder{arrayType, decoder}
return &arrayDecoder{ctx.ICodec, arrayType, decoder}
}
func encoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
@ -22,35 +23,54 @@ func encoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
return emptyArrayEncoder{}
}
encoder := EncoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem())
return &arrayEncoder{arrayType, encoder}
return &arrayEncoder{ctx.ICodec, arrayType, encoder}
}
//array-------------------------------------------------------------------------------------------------------------------------------
type arrayEncoder struct {
codec core.ICodec
arrayType *reflect2.UnsafeArrayType
elemEncoder core.IEncoder
}
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
func (this *arrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteArrayStart()
elemPtr := unsafe.Pointer(ptr)
encoder.elemEncoder.Encode(elemPtr, stream)
for i := 1; i < encoder.arrayType.Len(); i++ {
this.elemEncoder.Encode(elemPtr, stream)
for i := 1; i < this.arrayType.Len(); i++ {
stream.WriteMemberSplit()
elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
elemPtr = this.arrayType.UnsafeGetIndex(ptr, i)
this.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
if stream.Error() != nil && stream.Error() != io.EOF {
stream.SetErr(fmt.Errorf("%v: %s", encoder.arrayType, stream.Error().Error()))
stream.SetErr(fmt.Errorf("%v: %s", this.arrayType, stream.Error().Error()))
}
}
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
func (this *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
//编码对象到json数组
func (this *arrayEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error) {
ret = make([]string, this.arrayType.Len())
stream := this.codec.BorrowStream()
for i := 1; i < this.arrayType.Len(); i++ {
elemPtr := this.arrayType.UnsafeGetIndex(ptr, i)
this.elemEncoder.Encode(elemPtr, stream)
if stream.Error() != nil && stream.Error() != io.EOF {
err = stream.Error()
return
}
ret[i] = BytesToString(stream.Buffer())
stream.Reset(512)
}
return
}
type arrayDecoder struct {
codec core.ICodec
arrayType *reflect2.UnsafeArrayType
elemDecoder core.IDecoder
}
@ -83,6 +103,26 @@ func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
}
}
func (this *arrayDecoder) DecodeForSliceJson(ptr unsafe.Pointer, data []string) (err error) {
arrayType := this.arrayType
if data == nil {
err = errors.New("extra is nil")
return
}
extra := this.codec.BorrowExtractor([]byte{})
arrayType.UnsafeGetIndex(ptr, len(data))
for i, v := range data {
elemPtr := arrayType.UnsafeGetIndex(ptr, i)
extra.ResetBytes(StringToBytes(v))
this.elemDecoder.Decode(elemPtr, extra)
if extra.Error() != nil && extra.Error() != io.EOF {
err = extra.Error()
return
}
}
return
}
type emptyArrayEncoder struct{}
func (this emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {

View File

@ -2,6 +2,7 @@ package factory
import (
"fmt"
"io"
"reflect"
"unsafe"
@ -15,6 +16,7 @@ func decoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
keyDecoder := decoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key())
elemDecoder := DecoderOfType(ctx.Append("[mapElem]"), mapType.Elem())
return &mapDecoder{
codec: ctx.ICodec,
mapType: mapType,
keyType: mapType.Key(),
elemType: mapType.Elem(),
@ -26,6 +28,7 @@ func decoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
func encoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
mapType := typ.(*reflect2.UnsafeMapType)
return &mapEncoder{
codec: ctx.ICodec,
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()),
elemEncoder: EncoderOfType(ctx.Append("[mapElem]"), mapType.Elem()),
@ -75,6 +78,7 @@ func encoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
//Map--------------------------------------------------------------------------------------------------------------------------------------
type mapEncoder struct {
codec core.ICodec
mapType *reflect2.UnsafeMapType
keyEncoder core.IEncoder
elemEncoder core.IEncoder
@ -99,12 +103,37 @@ func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteObjectEnd()
}
func (this *mapEncoder) EncodeToMapString(ptr unsafe.Pointer) (ret map[string]string, err error) {
ret = make(map[string]string)
keystream := this.codec.BorrowStream()
elemstream := this.codec.BorrowStream()
iter := this.mapType.UnsafeIterate(ptr)
for i := 0; iter.HasNext(); i++ {
key, elem := iter.UnsafeNext()
this.keyEncoder.Encode(key, keystream)
if keystream.Error() != nil && keystream.Error() != io.EOF {
err = keystream.Error()
return
}
this.elemEncoder.Encode(elem, elemstream)
if elemstream.Error() != nil && elemstream.Error() != io.EOF {
err = elemstream.Error()
return
}
ret[BytesToString(keystream.Buffer())] = BytesToString(elemstream.Buffer())
keystream.Reset(512)
elemstream.Reset(512)
}
return
}
func (this *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
iter := this.mapType.UnsafeIterate(ptr)
return !iter.HasNext()
}
type mapDecoder struct {
codec core.ICodec
mapType *reflect2.UnsafeMapType
keyType reflect2.Type
elemType reflect2.Type
@ -150,6 +179,30 @@ func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
extra.ReadObjectEnd()
}
//解码对象从MapJson 中
func (this *mapDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) {
keyext := this.codec.BorrowExtractor([]byte{})
elemext := this.codec.BorrowExtractor([]byte{})
for k, v := range extra {
keyext.ResetBytes(StringToBytes(k))
key := this.keyType.UnsafeNew()
this.keyDecoder.Decode(key, keyext)
if keyext.Error() != nil && keyext.Error() != io.EOF {
err = keyext.Error()
return
}
elemext.ResetBytes(StringToBytes(v))
elem := this.elemType.UnsafeNew()
this.elemDecoder.Decode(elem, elemext)
this.mapType.UnsafeSetIndex(ptr, key, elem)
if elemext.Error() != nil && elemext.Error() != io.EOF {
err = elemext.Error()
return
}
}
return
}
//NumericMap-------------------------------------------------------------------------------------------------------------------------------
type numericMapKeyDecoder struct {
decoder core.IDecoder

View File

@ -1,6 +1,7 @@
package factory
import (
"fmt"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
@ -29,16 +30,16 @@ type OptionalDecoder struct {
ValueDecoder core.IDecoder
}
func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
func (this *OptionalDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if extra.ReadNil() {
*((*unsafe.Pointer)(ptr)) = nil
} else {
if *((*unsafe.Pointer)(ptr)) == nil {
newPtr := decoder.ValueType.UnsafeNew()
decoder.ValueDecoder.Decode(newPtr, extra)
newPtr := this.ValueType.UnsafeNew()
this.ValueDecoder.Decode(newPtr, extra)
*((*unsafe.Pointer)(ptr)) = newPtr
} else {
decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), extra)
this.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), extra)
}
}
}
@ -47,37 +48,46 @@ type OptionalEncoder struct {
ValueEncoder core.IEncoder
}
func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
func (this *OptionalEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
this.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
func (this *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil
}
func (this *OptionalEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) {
if encoderMapJson, ok := this.ValueEncoder.(core.IEncoderMapJson); !ok {
err = fmt.Errorf("encoder %T not support EncodeToMapJson", this.ValueEncoder)
return
} else {
return encoderMapJson.EncodeToMapJson(ptr)
}
}
//reference--------------------------------------------------------------------------------------------------------------------
type referenceEncoder struct {
encoder core.IEncoder
}
func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
func (this *referenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
this.encoder.Encode(unsafe.Pointer(&ptr), stream)
}
func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
func (this *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return this.encoder.IsEmpty(unsafe.Pointer(&ptr))
}
type referenceDecoder struct {
decoder core.IDecoder
}
func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
decoder.decoder.Decode(unsafe.Pointer(&ptr), extra)
func (this *referenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
this.decoder.Decode(unsafe.Pointer(&ptr), extra)
}
//dereference--------------------------------------------------------------------------------------------------------------------
@ -100,28 +110,28 @@ type dereferenceEncoder struct {
ValueEncoder core.IEncoder
}
func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
func (this *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
this.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
func (this *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
dePtr := *((*unsafe.Pointer)(ptr))
if dePtr == nil {
return true
}
return encoder.ValueEncoder.IsEmpty(dePtr)
return this.ValueEncoder.IsEmpty(dePtr)
}
func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
func (this *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
deReferenced := *((*unsafe.Pointer)(ptr))
if deReferenced == nil {
return true
}
isEmbeddedPtrNil, converted := encoder.ValueEncoder.(core.IsEmbeddedPtrNil)
isEmbeddedPtrNil, converted := this.ValueEncoder.(core.IsEmbeddedPtrNil)
if !converted {
return false
}

View File

@ -1,6 +1,7 @@
package factory
import (
"errors"
"fmt"
"io"
"unsafe"
@ -13,53 +14,80 @@ import (
func decoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
decoder := DecoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem())
return &sliceDecoder{sliceType, decoder}
return &sliceDecoder{ctx.ICodec, sliceType, decoder}
}
func encoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
encoder := EncoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem())
return &sliceEncoder{sliceType, encoder}
return &sliceEncoder{ctx.ICodec, sliceType, encoder}
}
type sliceEncoder struct {
codec core.ICodec
sliceType *reflect2.UnsafeSliceType
elemEncoder core.IEncoder
}
func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if encoder.sliceType.UnsafeIsNil(ptr) {
func (this *sliceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if this.sliceType.UnsafeIsNil(ptr) {
stream.WriteNil()
return
}
length := encoder.sliceType.UnsafeLengthOf(ptr)
length := this.sliceType.UnsafeLengthOf(ptr)
if length == 0 {
stream.WriteEmptyArray()
return
}
stream.WriteArrayStart()
encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream)
this.elemEncoder.Encode(this.sliceType.UnsafeGetIndex(ptr, 0), stream)
for i := 1; i < length; i++ {
stream.WriteMemberSplit()
elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
elemPtr := this.sliceType.UnsafeGetIndex(ptr, i)
this.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
if stream.Error() != nil && stream.Error() != io.EOF {
stream.SetErr(fmt.Errorf("%v: %s", encoder.sliceType, stream.Error().Error()))
stream.SetErr(fmt.Errorf("%v: %s", this.sliceType, stream.Error().Error()))
}
}
func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.sliceType.UnsafeLengthOf(ptr) == 0
func (this *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return this.sliceType.UnsafeLengthOf(ptr) == 0
}
//编码对象到json数组
func (this *sliceEncoder) EncodeToSliceJson(ptr unsafe.Pointer) (ret []string, err error) {
if this.sliceType.UnsafeIsNil(ptr) {
err = errors.New("val is nil")
return
}
length := this.sliceType.UnsafeLengthOf(ptr)
ret = make([]string, length)
if length == 0 {
return
}
stream := this.codec.BorrowStream()
for i := 1; i < length; i++ {
elemPtr := this.sliceType.UnsafeGetIndex(ptr, i)
this.elemEncoder.Encode(elemPtr, stream)
if stream.Error() != nil && stream.Error() != io.EOF {
err = stream.Error()
return
}
ret[i] = BytesToString(stream.Buffer())
stream.Reset(512)
}
return
}
type sliceDecoder struct {
codec core.ICodec
sliceType *reflect2.UnsafeSliceType
elemDecoder core.IDecoder
}
func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
sliceType := decoder.sliceType
func (this *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
sliceType := this.sliceType
if extra.ReadNil() {
sliceType.UnsafeSetNil(ptr)
return
@ -73,19 +101,39 @@ func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
}
sliceType.UnsafeGrow(ptr, 1)
elemPtr := sliceType.UnsafeGetIndex(ptr, 0)
decoder.elemDecoder.Decode(elemPtr, extra)
this.elemDecoder.Decode(elemPtr, extra)
length := 1
for extra.ReadMemberSplit() {
idx := length
length += 1
sliceType.UnsafeGrow(ptr, length)
elemPtr = sliceType.UnsafeGetIndex(ptr, idx)
decoder.elemDecoder.Decode(elemPtr, extra)
this.elemDecoder.Decode(elemPtr, extra)
}
if extra.ReadArrayEnd() {
return
}
if extra.Error() != nil && extra.Error() != io.EOF {
extra.SetErr(fmt.Errorf("%v: %s", decoder.sliceType, extra.Error().Error()))
extra.SetErr(fmt.Errorf("%v: %s", this.sliceType, extra.Error().Error()))
}
}
func (this *sliceDecoder) DecodeForSliceJson(ptr unsafe.Pointer, data []string) (err error) {
sliceType := this.sliceType
if data == nil {
err = errors.New("extra is nil")
return
}
extra := this.codec.BorrowExtractor([]byte{})
sliceType.UnsafeGrow(ptr, len(data))
for i, v := range data {
elemPtr := sliceType.UnsafeGetIndex(ptr, i)
extra.ResetBytes(StringToBytes(v))
this.elemDecoder.Decode(elemPtr, extra)
if extra.Error() != nil && extra.Error() != io.EOF {
err = extra.Error()
return
}
}
return
}

View File

@ -273,7 +273,7 @@ func (this *structEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
}
}
func (this *structEncoder) EncodeToMapString(ptr unsafe.Pointer) (ret map[string]string, err error) {
func (this *structEncoder) EncodeToMapJson(ptr unsafe.Pointer) (ret map[string]string, err error) {
ret = make(map[string]string)
stream := this.codec.BorrowStream()
for _, field := range this.fields {
@ -348,7 +348,7 @@ func (this *structDecoder) decodeField(ptr unsafe.Pointer, extra core.IExtractor
}
//解码对象从MapJson 中
func (this *structDecoder) DecodeForMapString(ptr unsafe.Pointer, extra map[string]string) (err error) {
func (this *structDecoder) DecodeForMapJson(ptr unsafe.Pointer, extra map[string]string) (err error) {
var fieldDecoder *structFieldDecoder
ext := this.codec.BorrowExtractor([]byte{})
for k, v := range extra {

View File

@ -2,6 +2,7 @@ package codec
import (
"go_dreamfactory/lego/sys/codec/core"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/mapstructure"
)
@ -15,6 +16,9 @@ func newOptions(config map[string]interface{}, opts ...core.Option) core.Options
for _, o := range opts {
o(&options)
}
if options.Debug && options.Log == nil {
options.Log = log.Clone()
}
return options
}
@ -25,5 +29,8 @@ func newOptionsByOption(opts ...core.Option) core.Options {
for _, o := range opts {
o(&options)
}
if options.Debug && options.Log == nil {
options.Log = log.Clone()
}
return options
}

View File

@ -19,7 +19,7 @@ type Test1Data struct {
Value int
}
func Test_sys(t *testing.T) {
func Test_sys_json(t *testing.T) {
if err := log.OnInit(nil); err != nil {
fmt.Printf("log init err:%v", err)
return
@ -34,3 +34,21 @@ func Test_sys(t *testing.T) {
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
}
}
func Test_sys_mapjson(t *testing.T) {
if err := log.OnInit(nil); err != nil {
fmt.Printf("log init err:%v", err)
return
}
if sys, err := codec.NewSys(); err != nil {
fmt.Printf("gin init err:%v", err)
} else {
m := map[string]interface{}{"liwe": 123, "aasd": "123"}
fmt.Printf("codec Marshal m:%s err:%v", m, err)
d, err := sys.MarshalMapJson(&TestData{Name: "http://liwei1dao.com?asd=1&dd=1", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}})
fmt.Printf("codec Marshal d:%s err:%v", d, err)
data := &TestData{}
err = sys.UnmarshalMapJson(d, data)
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
}
}

View File

@ -9,7 +9,6 @@ import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
@ -31,12 +30,12 @@ func (this *Mongodb) init() (err error) {
// return fmt.Errorf("数据库设置辅助节点 err=%s", err.Error())
// }
// wc := writeconcern.New(writeconcern.W(1))
readconcern.Majority()
// readconcern.Majority()
//链接mongo服务
opt := options.Client().ApplyURI(this.options.MongodbUrl)
// opt.SetLocalThreshold(3 * time.Second) //只使用与mongo操作耗时小于3秒的
// opt.SetMaxConnIdleTime(5 * time.Second) //指定连接可以保持空闲的最大毫秒数
opt.SetMaxPoolSize(this.options.MaxPoolSize) //使用最大的连接数
// opt.SetMaxPoolSize(this.options.MaxPoolSize) //使用最大的连接数
// opt.SetReadPreference(want) //表示只使用辅助节点
// opt.SetReadConcern(readconcern.Majority()) //指定查询应返回实例的最新数据确认为,已写入副本集中的大多数成员
// opt.SetWriteConcern(wc) //请求确认写操作传播到大多数mongod实例
@ -48,7 +47,6 @@ func (this *Mongodb) init() (err error) {
return fmt.Errorf("数据库不可用 err=%s", err.Error())
}
this.Database = client.Database(this.options.MongodbDatabase)
}
return
}

View File

@ -2,15 +2,14 @@ package cluster
import (
"context"
"go_dreamfactory/lego/utils/codec"
"go_dreamfactory/lego/sys/redis/core"
"time"
"github.com/go-redis/redis/v8"
)
func NewSys(RedisUrl []string, RedisPassword string, timeOut time.Duration,
encode codec.IEncoder,
decode codec.IDecoder,
codec core.ICodec,
) (sys *Redis, err error) {
var (
client *redis.ClusterClient
@ -22,8 +21,7 @@ func NewSys(RedisUrl []string, RedisPassword string, timeOut time.Duration,
sys = &Redis{
client: client,
timeOut: timeOut,
encode: encode,
decode: decode,
codec: codec,
}
_, err = sys.Ping()
return
@ -32,8 +30,7 @@ func NewSys(RedisUrl []string, RedisPassword string, timeOut time.Duration,
type Redis struct {
client *redis.ClusterClient
timeOut time.Duration
encode codec.IEncoder
decode codec.IDecoder
codec core.ICodec
}
func (this *Redis) getContext() (ctx context.Context) {

View File

@ -36,7 +36,7 @@ func (this *Redis) HMSet(key string, v interface{}) (err error) {
agrs = append(agrs, "HMSET")
agrs = append(agrs, key)
var data map[string]string
if data, err = this.encode.EncoderToMapString(v); err != nil {
if data, err = this.codec.MarshalMap(v); err != nil {
return
}
for k, v := range data {
@ -52,13 +52,13 @@ Redis Hget 命令用于返回哈希表中指定字段的值
func (this *Redis) HGet(key string, field string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "HGET", key, field)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
if len(_result) == 0 {
err = redis.Nil
return
}
err = this.decode.DecoderString(_result, v)
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -76,7 +76,7 @@ func (this *Redis) HGetAll(key string, v interface{}) (err error) {
err = redis.Nil
return
}
err = this.decode.DecoderMapString(_result, v)
err = this.codec.UnmarshalMap(_result, v)
}
return
}
@ -140,7 +140,7 @@ func (this *Redis) HMGet(key string, v interface{}, fields ...string) (err error
err = redis.Nil
return
}
err = this.decode.DecoderMapString(_result, v)
err = this.codec.UnmarshalMap(_result, v)
}
return
}
@ -152,7 +152,7 @@ Redis Hset 命令用于为哈希表中的字段赋值
*/
func (this *Redis) HSet(key string, field string, value interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.encode.Encoder(value); err == nil {
if resultvalue, err = this.codec.Marshal(value); err == nil {
err = this.client.Do(this.getContext(), "HSET", key, field, resultvalue).Err()
}
return
@ -166,7 +166,7 @@ Redis Hsetnx 命令用于为哈希表中不存在的的字段赋值
*/
func (this *Redis) HSetNX(key string, field string, value interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.encode.Encoder(value); err == nil {
if resultvalue, err = this.codec.Marshal(value); err == nil {
err = this.client.Do(this.getContext(), "HSETNX", key, field, resultvalue).Err()
}
return

View File

@ -10,13 +10,13 @@ Redis Lindex 命令用于通过索引获取列表中的元素。你也可以使
func (this *Redis) Lindex(key string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "LINDEX", key)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
if len(_result) == 0 {
err = redis.Nil
return
}
err = this.decode.DecoderString(_result, v)
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -28,13 +28,13 @@ Redis Linsert 命令用于在列表的元素前或者后插入元素。当指定
*/
func (this *Redis) Linsert(key string, isbefore bool, tager interface{}, value interface{}) (err error) {
var (
tagervalue string
resultvalue string
tagervalue []byte
resultvalue []byte
)
if tagervalue, err = this.encode.EncoderString(tager); err != nil {
if tagervalue, err = this.codec.Marshal(tager); err != nil {
return
}
if resultvalue, err = this.encode.EncoderString(value); err != nil {
if resultvalue, err = this.codec.Marshal(value); err != nil {
return
}
if isbefore {
@ -59,9 +59,9 @@ Redis Lpop 命令用于移除并返回列表的第一个元素
func (this *Redis) LPop(key string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "LPOP", key)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -73,7 +73,7 @@ func (this *Redis) LPush(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "LPUSH")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -87,7 +87,7 @@ func (this *Redis) LPushX(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "LPUSHX")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -103,7 +103,7 @@ func (this *Redis) LRange(key string, start, end int, v interface{}) (err error)
cmd := redis.NewStringSliceCmd(this.getContext(), "LRANGE", key, start, end)
this.client.Process(this.getContext(), cmd)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -116,8 +116,8 @@ count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,
count = 0 : 移除表中所有与 VALUE 相等的值
*/
func (this *Redis) LRem(key string, count int, target interface{}) (err error) {
var resultvalue string
if resultvalue, err = this.encode.EncoderString(target); err != nil {
var resultvalue []byte
if resultvalue, err = this.codec.Marshal(target); err != nil {
return
}
err = this.client.Do(this.getContext(), "LREM", key, count, resultvalue).Err()
@ -129,8 +129,8 @@ Redis Lset 通过索引来设置元素的值。
当索引参数超出范围或对一个空列表进行 LSET 返回一个错误
*/
func (this *Redis) LSet(key string, index int, value interface{}) (err error) {
var resultvalue string
if resultvalue, err = this.encode.EncoderString(value); err == nil {
var resultvalue []byte
if resultvalue, err = this.codec.Marshal(value); err == nil {
return
}
err = this.client.Do(this.getContext(), "LSET", key, index, resultvalue).Err()
@ -153,9 +153,9 @@ Redis Rpop 命令用于移除列表的最后一个元素,返回值为移除的
func (this *Redis) Rpop(key string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "RPOP", key)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -166,9 +166,9 @@ Redis Rpoplpush 命令用于移除列表的最后一个元素,并将该元素
func (this *Redis) RPopLPush(oldkey string, newkey string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "RPOPLPUSH", oldkey, newkey)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -182,7 +182,7 @@ func (this *Redis) RPush(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "RPUSH")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -196,7 +196,7 @@ func (this *Redis) RPushX(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "RPUSHX")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()

View File

@ -10,7 +10,7 @@ func (this *Redis) SAdd(key string, values ...interface{}) (err error) {
agrs = append(agrs, "SADD")
agrs = append(agrs, key)
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -34,7 +34,7 @@ func (this *Redis) SDiff(v interface{}, keys ...string) (err error) {
var _result []string
cmd := this.client.SDiff(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -54,7 +54,7 @@ func (this *Redis) SInter(v interface{}, keys ...string) (err error) {
var _result []string
cmd := this.client.SInter(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -82,7 +82,7 @@ func (this *Redis) SMembers(v interface{}, key string) (err error) {
var _result []string
cmd := this.client.SMembers(this.getContext(), key)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -137,7 +137,7 @@ func (this *Redis) SUnion(v interface{}, keys ...string) (err error) {
var _result []string
cmd := this.client.SUnion(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}

View File

@ -11,8 +11,8 @@ import (
命令用于设置给定 key 的值如果 key 已经存储其他值 SET 就覆写旧值且无视类型
*/
func (this *Redis) Set(key string, value interface{}, expiration time.Duration) (err error) {
var result string
if result, err = this.encode.EncoderString(value); err != nil {
var result []byte
if result, err = this.codec.Marshal(value); err != nil {
return
}
err = this.client.Set(this.getContext(), key, result, expiration).Err()
@ -37,7 +37,7 @@ func (this *Redis) MSet(v map[string]interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "MSET")
for k, v := range v {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, k, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -51,7 +51,7 @@ func (this *Redis) MSetNX(v map[string]interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "MSETNX")
for k, v := range v {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, k, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -117,8 +117,8 @@ Redis Append 命令用于为指定的 key 追加值。
如果 key 不存在 APPEND 就简单地将给定 key 设为 value 就像执行 SET key value 一样
*/
func (this *Redis) Append(key string, value interface{}) (err error) {
var result string
if result, err = this.encode.EncoderString(value); err != nil {
var result []byte
if result, err = this.codec.Marshal(value); err != nil {
return
}
err = this.client.Do(this.getContext(), "APPEND", key, result).Err()
@ -129,9 +129,9 @@ func (this *Redis) Append(key string, value interface{}) (err error) {
命令用于设置给定 key 的值如果 key 已经存储其他值 SET 就覆写旧值且无视类型
*/
func (this *Redis) Get(key string, value interface{}) (err error) {
var result string
if result, err = this.client.Get(this.getContext(), key).Result(); err == nil {
err = this.decode.DecoderString(result, value)
var result []byte
if result, err = this.client.Get(this.getContext(), key).Bytes(); err == nil {
err = this.codec.Unmarshal(result, value)
}
return
}
@ -141,14 +141,14 @@ func (this *Redis) Get(key string, value interface{}) (err error) {
*/
func (this *Redis) GetSet(key string, value interface{}, result interface{}) (err error) {
var (
_value string
_value []byte
)
if _value, err = this.encode.EncoderString(value); err == nil {
if _value, err = this.codec.Marshal(value); err == nil {
cmd := redis.NewStringCmd(this.getContext(), "GETSET", key, _value)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, result)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, result)
}
}
return
@ -169,7 +169,7 @@ func (this *Redis) MGet(v interface{}, keys ...string) (err error) {
if result, err = cmd.Result(); err != nil {
return
}
err = this.decode.DecoderSliceString(result, v)
err = this.codec.UnmarshalSlice(result, v)
return
}

View File

@ -59,7 +59,7 @@ func (this *Redis) ZRange(key string, start int64, stop int64, v interface{}) (e
var _result []string
cmd := this.client.ZRange(this.getContext(), key, start, stop)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -71,7 +71,7 @@ func (this *Redis) ZRangeByLex(key string, opt *redis.ZRangeBy, v interface{}) (
var _result []string
cmd := this.client.ZRangeByLex(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -83,7 +83,7 @@ func (this *Redis) ZRangeByScore(key string, opt *redis.ZRangeBy, v interface{})
var _result []string
cmd := this.client.ZRangeByScore(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -135,7 +135,7 @@ func (this *Redis) ZRevRange(key string, start int64, stop int64, v interface{})
var _result []string
cmd := this.client.ZRevRange(this.getContext(), key, start, stop)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -147,7 +147,7 @@ func (this *Redis) ZRevRangeByScore(key string, opt *redis.ZRangeBy, v interface
var _result []string
cmd := this.client.ZRevRangeByScore(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}

View File

@ -0,0 +1,12 @@
package core
type (
ICodec interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
MarshalMap(val interface{}) (ret map[string]string, err error)
UnmarshalMap(data map[string]string, val interface{}) (err error)
MarshalSlice(val interface{}) (ret []string, err error)
UnmarshalSlice(data []string, val interface{}) (err error)
}
)

View File

@ -3,6 +3,7 @@ package redis
import (
"time"
"go_dreamfactory/lego/sys/redis/core"
"go_dreamfactory/lego/utils/mapstructure"
)
@ -13,14 +14,6 @@ const (
Redis_Cluster
)
///redis 存储数据格式化类型
type RedisStorageTyoe int8
const (
JsonData RedisStorageTyoe = iota
ProtoData
)
type Option func(*Options)
type Options struct {
RedisType RedisType
@ -30,8 +23,8 @@ type Options struct {
Redis_Single_PoolSize int
Redis_Cluster_Addr []string
Redis_Cluster_Password string
RedisStorageType RedisStorageTyoe
TimeOut time.Duration
Codec core.ICodec
}
func SetRedisType(v RedisType) Option {
@ -74,11 +67,6 @@ func SetRedis_Cluster_Password(v string) Option {
o.Redis_Cluster_Password = v
}
}
func SetRedisStorageType(v RedisStorageTyoe) Option {
return func(o *Options) {
o.RedisStorageType = v
}
}
func SetTimeOut(v time.Duration) Option {
return func(o *Options) {
@ -86,6 +74,12 @@ func SetTimeOut(v time.Duration) Option {
}
}
func SetCodec(v core.ICodec) Option {
return func(o *Options) {
o.Codec = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) Options {
options := Options{
Redis_Single_Addr: "127.0.0.1:6379",

View File

@ -5,25 +5,15 @@ import (
"fmt"
"time"
jsoniter "github.com/json-iterator/go"
"go_dreamfactory/lego/sys/codec"
"go_dreamfactory/lego/sys/redis/cluster"
"go_dreamfactory/lego/sys/redis/single"
"go_dreamfactory/lego/utils/codec"
"github.com/go-redis/redis/v8"
"google.golang.org/protobuf/proto"
)
func newSys(options Options) (sys *Redis, err error) {
sys = &Redis{options: options}
if options.RedisStorageType == JsonData {
sys.decoder = &codec.Decoder{DefDecoder: jsoniter.Unmarshal}
sys.encoder = &codec.Encoder{DefEncoder: jsoniter.Marshal}
} else {
sys.decoder = &codec.Decoder{DefDecoder: func(buf []byte, v interface{}) error { return proto.Unmarshal(buf, v.(proto.Message)) }}
sys.encoder = &codec.Encoder{DefEncoder: func(v interface{}) (data []byte, err error) { return proto.Marshal(v.(proto.Message)) }}
}
err = sys.init()
return
}
@ -31,8 +21,6 @@ func newSys(options Options) (sys *Redis, err error) {
type Redis struct {
options Options
client IRedis
decoder codec.IDecoder
encoder codec.IEncoder
}
func (this *Redis) init() (err error) {
@ -43,16 +31,14 @@ func (this *Redis) init() (err error) {
this.options.Redis_Single_DB,
this.options.Redis_Single_PoolSize,
this.options.TimeOut,
this.encoder,
this.decoder,
this,
)
} else if this.options.RedisType == Redis_Cluster {
this.client, err = cluster.NewSys(
this.options.Redis_Cluster_Addr,
this.options.Redis_Cluster_Password,
this.options.TimeOut,
this.encoder,
this.decoder,
this,
)
} else {
err = fmt.Errorf("init Redis err:RedisType - %d", this.options.RedisType)
@ -360,3 +346,47 @@ func (this *Redis) ZUnionStore(dest string, store *redis.ZStore) (result int64,
func (this *Redis) ZScan(key string, _cursor uint64, match string, count int64) (keys []string, cursor uint64, err error) {
return this.client.ZScan(key, _cursor, match, count)
}
//Codec---------------------------------------------------------------------------------------------------------------------------------------
func (this *Redis) Marshal(v interface{}) ([]byte, error) {
if this.options.Codec != nil {
return this.options.Codec.Marshal(v)
} else {
return codec.MarshalJson(v)
}
}
func (this *Redis) Unmarshal(data []byte, v interface{}) error {
if this.options.Codec != nil {
return this.options.Codec.Unmarshal(data, v)
} else {
return codec.UnmarshalJson(data, v)
}
}
func (this *Redis) MarshalMap(val interface{}) (ret map[string]string, err error) {
if this.options.Codec != nil {
return this.options.Codec.MarshalMap(val)
} else {
return codec.MarshalMapJson(val)
}
}
func (this *Redis) UnmarshalMap(data map[string]string, val interface{}) (err error) {
if this.options.Codec != nil {
return this.options.Codec.UnmarshalMap(data, val)
} else {
return codec.UnmarshalMapJson(data, val)
}
}
func (this *Redis) MarshalSlice(val interface{}) (ret []string, err error) {
if this.options.Codec != nil {
return this.options.Codec.MarshalSlice(val)
} else {
return codec.MarshalSliceJson(val)
}
}
func (this *Redis) UnmarshalSlice(data []string, val interface{}) (err error) {
if this.options.Codec != nil {
return this.options.Codec.UnmarshalSlice(data, val)
} else {
return codec.UnmarshalSliceJson(data, val)
}
}

View File

@ -2,15 +2,14 @@ package single
import (
"context"
"go_dreamfactory/lego/utils/codec"
"go_dreamfactory/lego/sys/redis/core"
"time"
"github.com/go-redis/redis/v8"
)
func NewSys(RedisUrl, RedisPassword string, RedisDB, PoolSize int, timeOut time.Duration,
encode codec.IEncoder,
decode codec.IDecoder,
codec core.ICodec,
) (sys *Redis, err error) {
var (
client *redis.Client
@ -24,8 +23,7 @@ func NewSys(RedisUrl, RedisPassword string, RedisDB, PoolSize int, timeOut time.
sys = &Redis{
client: client,
timeOut: timeOut,
encode: encode,
decode: decode,
codec: codec,
}
_, err = sys.Ping()
return
@ -34,8 +32,7 @@ func NewSys(RedisUrl, RedisPassword string, RedisDB, PoolSize int, timeOut time.
type Redis struct {
client *redis.Client
timeOut time.Duration
encode codec.IEncoder
decode codec.IDecoder
codec core.ICodec
}
func (this *Redis) getContext() (ctx context.Context) {

View File

@ -36,7 +36,7 @@ func (this *Redis) HMSet(key string, v interface{}) (err error) {
agrs = append(agrs, "HMSET")
agrs = append(agrs, key)
var data map[string]string
if data, err = this.encode.EncoderToMapString(v); err != nil {
if data, err = this.codec.MarshalMap(v); err != nil {
return
}
for k, v := range data {
@ -52,9 +52,9 @@ Redis Hget 命令用于返回哈希表中指定字段的值
func (this *Redis) HGet(key string, field string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "HGET", key, field)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -71,7 +71,7 @@ func (this *Redis) HGetAll(key string, v interface{}) (err error) {
if len(_result) == 0 {
return redis.Nil
}
err = this.decode.DecoderMapString(_result, v)
err = this.codec.UnmarshalMap(_result, v)
}
return
}
@ -131,7 +131,7 @@ func (this *Redis) HMGet(key string, v interface{}, fields ...string) (err error
this.client.Process(this.getContext(), cmd)
var _result map[string]string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderMapString(_result, v)
err = this.codec.UnmarshalMap(_result, v)
}
return
}
@ -143,7 +143,7 @@ Redis Hset 命令用于为哈希表中的字段赋值
*/
func (this *Redis) HSet(key string, field string, value interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.encode.Encoder(value); err == nil {
if resultvalue, err = this.codec.Marshal(value); err == nil {
err = this.client.Do(this.getContext(), "HSET", key, field, resultvalue).Err()
}
return
@ -157,7 +157,7 @@ Redis Hsetnx 命令用于为哈希表中不存在的的字段赋值
*/
func (this *Redis) HSetNX(key string, field string, value interface{}) (err error) {
var resultvalue []byte
if resultvalue, err = this.encode.Encoder(value); err == nil {
if resultvalue, err = this.codec.Marshal(value); err == nil {
err = this.client.Do(this.getContext(), "HSETNX", key, field, resultvalue).Err()
}
return

View File

@ -10,9 +10,9 @@ Redis Lindex 命令用于通过索引获取列表中的元素。你也可以使
func (this *Redis) Lindex(key string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "LINDEX", key)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -24,13 +24,13 @@ Redis Linsert 命令用于在列表的元素前或者后插入元素。当指定
*/
func (this *Redis) Linsert(key string, isbefore bool, tager interface{}, value interface{}) (err error) {
var (
tagervalue string
resultvalue string
tagervalue []byte
resultvalue []byte
)
if tagervalue, err = this.encode.EncoderString(tager); err != nil {
if tagervalue, err = this.codec.Marshal(tager); err != nil {
return
}
if resultvalue, err = this.encode.EncoderString(value); err != nil {
if resultvalue, err = this.codec.Marshal(value); err != nil {
return
}
if isbefore {
@ -55,9 +55,9 @@ Redis Lpop 命令用于移除并返回列表的第一个元素
func (this *Redis) LPop(key string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "LPOP", key)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -69,7 +69,7 @@ func (this *Redis) LPush(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "LPUSH")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -83,7 +83,7 @@ func (this *Redis) LPushX(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "LPUSHX")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -99,7 +99,7 @@ func (this *Redis) LRange(key string, start, end int, v interface{}) (err error)
cmd := redis.NewStringSliceCmd(this.getContext(), "LRANGE", key, start, end)
this.client.Process(this.getContext(), cmd)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -112,8 +112,8 @@ count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,
count = 0 : 移除表中所有与 VALUE 相等的值
*/
func (this *Redis) LRem(key string, count int, target interface{}) (err error) {
var resultvalue string
if resultvalue, err = this.encode.EncoderString(target); err != nil {
var resultvalue []byte
if resultvalue, err = this.codec.Marshal(target); err != nil {
return
}
err = this.client.Do(this.getContext(), "LREM", key, count, resultvalue).Err()
@ -125,8 +125,8 @@ Redis Lset 通过索引来设置元素的值。
当索引参数超出范围或对一个空列表进行 LSET 返回一个错误
*/
func (this *Redis) LSet(key string, index int, value interface{}) (err error) {
var resultvalue string
if resultvalue, err = this.encode.EncoderString(value); err == nil {
var resultvalue []byte
if resultvalue, err = this.codec.Marshal(value); err == nil {
return
}
err = this.client.Do(this.getContext(), "LSET", key, index, resultvalue).Err()
@ -149,9 +149,9 @@ Redis Rpop 命令用于移除列表的最后一个元素,返回值为移除的
func (this *Redis) Rpop(key string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "RPOP", key)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -162,9 +162,9 @@ Redis Rpoplpush 命令用于移除列表的最后一个元素,并将该元素
func (this *Redis) RPopLPush(oldkey string, newkey string, v interface{}) (err error) {
cmd := redis.NewStringCmd(this.getContext(), "RPOPLPUSH", oldkey, newkey)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, v)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, v)
}
return
}
@ -178,7 +178,7 @@ func (this *Redis) RPush(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "RPUSH")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -192,7 +192,7 @@ func (this *Redis) RPushX(key string, values ...interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "RPUSHX")
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()

View File

@ -10,7 +10,7 @@ func (this *Redis) SAdd(key string, values ...interface{}) (err error) {
agrs = append(agrs, "SADD")
agrs = append(agrs, key)
for _, v := range values {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -34,7 +34,7 @@ func (this *Redis) SDiff(v interface{}, keys ...string) (err error) {
var _result []string
cmd := this.client.SDiff(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -54,7 +54,7 @@ func (this *Redis) SInter(v interface{}, keys ...string) (err error) {
var _result []string
cmd := this.client.SInter(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -82,7 +82,7 @@ func (this *Redis) SMembers(v interface{}, key string) (err error) {
var _result []string
cmd := this.client.SMembers(this.getContext(), key)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -137,7 +137,7 @@ func (this *Redis) SUnion(v interface{}, keys ...string) (err error) {
var _result []string
cmd := this.client.SUnion(this.getContext(), keys...)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}

View File

@ -11,8 +11,8 @@ import (
命令用于设置给定 key 的值如果 key 已经存储其他值 SET 就覆写旧值且无视类型
*/
func (this *Redis) Set(key string, value interface{}, expiration time.Duration) (err error) {
var result string
if result, err = this.encode.EncoderString(value); err != nil {
var result []byte
if result, err = this.codec.Marshal(value); err != nil {
return
}
err = this.client.Set(this.getContext(), key, result, expiration).Err()
@ -37,7 +37,7 @@ func (this *Redis) MSet(v map[string]interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "MSET")
for k, v := range v {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, k, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -51,7 +51,7 @@ func (this *Redis) MSetNX(v map[string]interface{}) (err error) {
agrs := make([]interface{}, 0)
agrs = append(agrs, "MSETNX")
for k, v := range v {
result, _ := this.encode.EncoderString(v)
result, _ := this.codec.Marshal(v)
agrs = append(agrs, k, result)
}
err = this.client.Do(this.getContext(), agrs...).Err()
@ -117,8 +117,8 @@ Redis Append 命令用于为指定的 key 追加值。
如果 key 不存在 APPEND 就简单地将给定 key 设为 value 就像执行 SET key value 一样
*/
func (this *Redis) Append(key string, value interface{}) (err error) {
var result string
if result, err = this.encode.EncoderString(value); err != nil {
var result []byte
if result, err = this.codec.Marshal(value); err != nil {
return
}
err = this.client.Do(this.getContext(), "APPEND", key, result).Err()
@ -129,9 +129,9 @@ func (this *Redis) Append(key string, value interface{}) (err error) {
命令用于设置给定 key 的值如果 key 已经存储其他值 SET 就覆写旧值且无视类型
*/
func (this *Redis) Get(key string, value interface{}) (err error) {
var result string
if result, err = this.client.Get(this.getContext(), key).Result(); err == nil {
err = this.decode.DecoderString(result, value)
var result []byte
if result, err = this.client.Get(this.getContext(), key).Bytes(); err == nil {
err = this.codec.Unmarshal(result, value)
}
return
}
@ -141,14 +141,14 @@ func (this *Redis) Get(key string, value interface{}) (err error) {
*/
func (this *Redis) GetSet(key string, value interface{}, result interface{}) (err error) {
var (
_value string
_value []byte
)
if _value, err = this.encode.EncoderString(value); err == nil {
if _value, err = this.codec.Marshal(value); err == nil {
cmd := redis.NewStringCmd(this.getContext(), "GETSET", key, _value)
this.client.Process(this.getContext(), cmd)
var _result string
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderString(_result, result)
var _result []byte
if _result, err = cmd.Bytes(); err == nil {
err = this.codec.Unmarshal(_result, result)
}
}
return
@ -169,7 +169,7 @@ func (this *Redis) MGet(v interface{}, keys ...string) (err error) {
if result, err = cmd.Result(); err != nil {
return
}
err = this.decode.DecoderSliceString(result, v)
err = this.codec.UnmarshalSlice(result, v)
return
}

View File

@ -59,7 +59,7 @@ func (this *Redis) ZRange(key string, start int64, stop int64, v interface{}) (e
var _result []string
cmd := this.client.ZRange(this.getContext(), key, start, stop)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -71,7 +71,7 @@ func (this *Redis) ZRangeByLex(key string, opt *redis.ZRangeBy, v interface{}) (
var _result []string
cmd := this.client.ZRangeByLex(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -83,7 +83,7 @@ func (this *Redis) ZRangeByScore(key string, opt *redis.ZRangeBy, v interface{})
var _result []string
cmd := this.client.ZRangeByScore(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -135,7 +135,7 @@ func (this *Redis) ZRevRange(key string, start int64, stop int64, v interface{})
var _result []string
cmd := this.client.ZRevRange(this.getContext(), key, start, stop)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}
@ -147,7 +147,7 @@ func (this *Redis) ZRevRangeByScore(key string, opt *redis.ZRangeBy, v interface
var _result []string
cmd := this.client.ZRevRangeByScore(this.getContext(), key, opt)
if _result, err = cmd.Result(); err == nil {
err = this.decode.DecoderSliceString(_result, v)
err = this.codec.UnmarshalSlice(_result, v)
}
return
}

View File

@ -16,7 +16,6 @@ func TestMain(m *testing.M) {
redis.SetRedisType(redis.Redis_Cluster),
redis.SetRedis_Cluster_Addr([]string{"10.0.0.9:9001", "10.0.0.9:9002", "10.0.0.9:9003", "10.0.1.45:9004", "10.0.1.45:9005", "10.0.1.45:9006"}),
redis.SetRedis_Cluster_Password(""),
redis.SetRedisStorageType(redis.JsonData),
); err != nil {
fmt.Println("err:", err)
return

View File

@ -50,6 +50,15 @@ func TestMain(m *testing.M) {
defer os.Exit(m.Run())
}
func Test_GetList(t *testing.T) {
heroes := []*DBHero{}
GetList(&heroes)
}
func Test_GetList0(t *testing.T) {
heroes := []*DBHero{}
GetListO(&heroes)
}
func BenchmarkMarsh(b *testing.B) {
var (
@ -112,7 +121,7 @@ func GetList(data interface{}) (err error) {
//query from mgo
// if c, err = mdb.Mgo().Find(core.SqlTable("hero"), bson.M{}); err != nil {
if c, err = mgoDb.Collection("hreo").Find(context.Background(), bson.M{}); err != nil {
if c, err = mgoDb.Collection("hero").Find(context.Background(), bson.M{}); err != nil {
return err
} else {
var temp map[string]interface{} = make(map[string]interface{})
@ -270,7 +279,9 @@ func BenchmarkSimple(b *testing.B) {
// f, _ := os.Create("c://pprof2")
// pprof.WriteHeapProfile(f)
// defer f.Close()
heroes := []*DBHero{}
for i := 0; i < b.N; i++ {
GetList4(new(DBHero))
// GetList4(new(DBHero))
GetList(&heroes)
}
}