1
0
mirror of https://github.com/redis/go-redis.git synced 2025-08-08 23:42:06 +03:00

Add StructValue so we don't need temp slices to pass keys and values

This commit is contained in:
Vladimir Mihailenco
2021-02-03 12:45:02 +02:00
parent 600f1665a0
commit bd234b91fe
4 changed files with 98 additions and 86 deletions

View File

@@ -6,17 +6,6 @@ import (
"sync"
)
// structField represents a single field in a target struct.
type structField struct {
index int
fn decoderFunc
}
// structFields contains the list of all fields in a target struct.
type structFields struct {
m map[string]*structField
}
// structMap contains the map of struct fields for target structs
// indexed by the struct type.
type structMap struct {
@@ -27,37 +16,38 @@ func newStructMap() *structMap {
return new(structMap)
}
func (s *structMap) get(t reflect.Type) *structFields {
func (s *structMap) get(t reflect.Type) *structSpec {
if v, ok := s.m.Load(t); ok {
return v.(*structFields)
return v.(*structSpec)
}
fMap := getStructFields(t, "redis")
s.m.Store(t, fMap)
return fMap
spec := newStructSpec(t, "redis")
s.m.Store(t, spec)
return spec
}
func newStructFields() *structFields {
return &structFields{
m: make(map[string]*structField),
}
//------------------------------------------------------------------------------
// structSpec contains the list of all fields in a target struct.
type structSpec struct {
m map[string]*structField
}
func (s *structFields) set(tag string, sf *structField) {
func (s *structSpec) set(tag string, sf *structField) {
s.m[tag] = sf
}
func (s *structFields) get(tag string) (*structField, bool) {
func (s *structSpec) get(tag string) (*structField, bool) {
f, ok := s.m[tag]
return f, ok
}
func getStructFields(t reflect.Type, fieldTag string) *structFields {
var (
num = t.NumField()
out = newStructFields()
)
func newStructSpec(t reflect.Type, fieldTag string) *structSpec {
out := &structSpec{
m: make(map[string]*structField),
}
num := t.NumField()
for i := 0; i < num; i++ {
f := t.Field(i)
@@ -77,3 +67,26 @@ func getStructFields(t reflect.Type, fieldTag string) *structFields {
return out
}
//------------------------------------------------------------------------------
// structField represents a single field in a target struct.
type structField struct {
index int
fn decoderFunc
}
//------------------------------------------------------------------------------
type StructValue struct {
spec *structSpec
value reflect.Value
}
func (s StructValue) Scan(key string, value string) error {
field, ok := s.spec.m[key]
if !ok {
return nil
}
return field.fn(s.value.Field(field.index), value)
}