package redis import ( "encoding/json" "errors" "reflect" "apigo.cc/go/cast" ) type Result struct { bytesData []byte keys []string bytesDatas [][]byte Error error } func (rs *Result) Int() int { return cast.Int(rs.String()) } func (rs *Result) Int8() int8 { return int8(cast.Int64(rs.String())) } func (rs *Result) Int16() int16 { return int16(cast.Int64(rs.String())) } func (rs *Result) Int32() int32 { return int32(cast.Int64(rs.String())) } func (rs *Result) Int64() int64 { return cast.Int64(rs.String()) } func (rs *Result) Uint() uint { return cast.Uint(rs.String()) } func (rs *Result) Uint8() uint8 { return uint8(cast.Uint64(rs.String())) } func (rs *Result) Uint16() uint16 { return uint16(cast.Uint64(rs.String())) } func (rs *Result) Uint32() uint32 { return uint32(cast.Uint64(rs.String())) } func (rs *Result) Uint64() uint64 { return cast.Uint64(rs.String()) } func (rs *Result) Float() float32 { return cast.Float(rs.String()) } func (rs *Result) Float64() float64 { return cast.Float64(rs.String()) } func (rs *Result) String() string { return string(rs.bytes()) } func (rs *Result) Bytes() []byte { return rs.bytes() } func (rs *Result) Bool() bool { return cast.Bool(rs.String()) } func (rs *Result) Ints() []int { if rs.bytesDatas != nil { r := make([]int, len(rs.bytesDatas)) for i, v := range rs.bytesDatas { r[i] = cast.Int(string(v)) } return r } else if rs.bytesData != nil { var r []int _ = rs.To(&r) return r } return []int{} } func (rs *Result) Strings() []string { if rs.bytesDatas != nil { r := make([]string, len(rs.bytesDatas)) for i, v := range rs.bytesDatas { r[i] = string(v) } return r } else if rs.bytesData != nil { var r []string _ = rs.To(&r) return r } return []string{} } func (rs *Result) Results() []Result { if rs.bytesDatas != nil { r := make([]Result, len(rs.bytesDatas)) for i, v := range rs.bytesDatas { r[i].bytesData = v } return r } else if rs.bytesData != nil { var m []string _ = rs.To(&m) r := make([]Result, len(m)) for k, v := range m { r[k] = Result{bytesData: []byte(v)} } return r } return []Result{} } func (rs *Result) ResultMap() map[string]*Result { if rs.bytesDatas != nil && rs.keys != nil { r := make(map[string]*Result) n := len(rs.bytesDatas) for i, k := range rs.keys { if i < n { r[k] = &Result{bytesData: rs.bytesDatas[i]} } } return r } else if rs.bytesData != nil { r := make(map[string]*Result) var m map[string]string _ = rs.To(&m) for k, v := range m { r[k] = &Result{bytesData: []byte(v)} } return r } return map[string]*Result{} } func (rs *Result) StringMap() map[string]string { rm := rs.ResultMap() m := make(map[string]string) for k, r := range rm { m[k] = r.String() } return m } func (rs *Result) IntMap() map[string]int { rm := rs.ResultMap() m := make(map[string]int) for k, r := range rm { m[k] = r.Int() } return m } func (rs *Result) bytes() []byte { if rs.bytesData != nil { return rs.bytesData } else if rs.bytesDatas != nil { return cast.MustJSONBytes(rs.Strings()) } return []byte{} } func (rs *Result) ToValue(t reflect.Type) reflect.Value { v := reflect.New(t).Elem() switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v.SetInt(rs.Int64()) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: v.SetUint(rs.Uint64()) case reflect.Float32, reflect.Float64: v.SetFloat(rs.Float64()) case reflect.Bool: v.SetBool(rs.Bool()) case reflect.String: v.SetString(rs.String()) case reflect.Map, reflect.Slice, reflect.Struct: _ = rs.To(v.Addr().Interface()) } return v } // To 使用泛型进行反序列化 func To[T any](rs *Result) T { var out T _ = rs.To(&out) return out } func (rs *Result) To(result any) error { if result == nil { return errors.New("result target is nil") } if rs.bytesData != nil { if len(rs.bytesData) > 0 { // 优先使用 json.Unmarshal 以支持自定义 Unmarshaler (如 time.Time) return json.Unmarshal(rs.bytesData, result) } return nil } t := reflect.TypeOf(result) v := reflect.ValueOf(result) if t.Kind() != reflect.Ptr || v.IsNil() { return errors.New("result target must be a non-nil pointer") } t = t.Elem() v = v.Elem() if (t.Kind() == reflect.Struct || t.Kind() == reflect.Map) && rs.keys != nil && rs.bytesDatas != nil { rm := rs.ResultMap() for k, r := range rm { if t.Kind() == reflect.Struct { k = cast.GetUpperName(k) sf, found := t.FieldByName(k) if found { fieldV := v.FieldByName(k) if fieldV.CanSet() { fieldV.Set(r.ToValue(sf.Type)) } } } else if t.Kind() == reflect.Map { if v.IsNil() { v.Set(reflect.MakeMap(t)) } v.SetMapIndex(reflect.ValueOf(k), r.ToValue(t.Elem())) } } } else if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 && rs.bytesDatas != nil { results := rs.Results() for _, r := range results { v = reflect.Append(v, r.ToValue(t.Elem())) } reflect.ValueOf(result).Elem().Set(v) } return nil }