From bf334e773819574a898717f5a709e15cecaa43ff Mon Sep 17 00:00:00 2001 From: wjdqhry Date: Fri, 17 Dec 2021 11:54:43 +0900 Subject: [PATCH] feat: enable struct on HSet --- commands.go | 30 ++++++++++++++++++++++++++++++ example_test.go | 14 ++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/commands.go b/commands.go index dfe8d0bb..5ee66fab 100644 --- a/commands.go +++ b/commands.go @@ -4,6 +4,7 @@ import ( "context" "errors" "io" + "reflect" "time" "github.com/go-redis/redis/v8/internal" @@ -78,6 +79,29 @@ func appendArg(dst []interface{}, arg interface{}) []interface{} { } } +func structToMap(items interface{}) map[string]interface{} { + res := map[string]interface{}{} + if items == nil { + return res + } + v := reflect.TypeOf(items) + reflectValue := reflect.Indirect(reflect.ValueOf(items)) + + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + for i := 0; i < v.NumField(); i++ { + tag := v.Field(i).Tag.Get("json") + + if tag != "" && v.Field(i).Type.Kind() != reflect.Struct { + field := reflectValue.Field(i).Interface() + res[tag] = field + } + } + + return res +} + type Cmdable interface { Pipeline() Pipeliner Pipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error) @@ -1261,9 +1285,15 @@ func (c cmdable) HMGet(ctx context.Context, key string, fields ...string) *Slice // - HSet("myhash", "key1", "value1", "key2", "value2") // - HSet("myhash", []string{"key1", "value1", "key2", "value2"}) // - HSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"}) +// - HSet("myhash", struct{Key1: "value1"; Key2: "value2"}) // // Note that it requires Redis v4 for multiple field/value pairs support. func (c cmdable) HSet(ctx context.Context, key string, values ...interface{}) *IntCmd { + if len(values) == 1 { + if reflect.ValueOf(values[0]).Kind() == reflect.Struct { + values = []interface{}{structToMap(values[0])} + } + } args := make([]interface{}, 2, 2+len(values)) args[0] = "hset" args[1] = key diff --git a/example_test.go b/example_test.go index f0158096..46bed6f0 100644 --- a/example_test.go +++ b/example_test.go @@ -197,6 +197,20 @@ func ExampleClient_SetEX() { } } +func ExampleClient_HSet() { + type Items struct { + Key1 string `json:"key1"` + Key2 string `json:"key2"` + } + items := Items{"field1", "field2"} + // Last argument is expiration. Zero means the key has no + // expiration time. + err := rdb.HSet(ctx, "key", items).Err() + if err != nil { + panic(err) + } +} + func ExampleClient_Incr() { result, err := rdb.Incr(ctx, "counter").Result() if err != nil {