From 37c057b8e597c5e8a0e372337f6a8ad27f6030af Mon Sep 17 00:00:00 2001 From: Monkey Date: Mon, 3 Apr 2023 15:43:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20read=20the=20structure=20to=20increase?= =?UTF-8?q?=20the=20judgment=20of=20the=20omitempty=20op=E2=80=A6=20(#2529?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: read the structure to increase the judgment of the omitempty option, the same as json Signed-off-by: monkey92t --- commands.go | 41 ++++++++++++++++++++++++++++++++++++++--- commands_test.go | 19 ++++++++++++++++++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/commands.go b/commands.go index 4aa0c882..588b3a4f 100644 --- a/commands.go +++ b/commands.go @@ -106,20 +106,55 @@ func appendStructField(dst []interface{}, v reflect.Value) []interface{} { if tag == "" || tag == "-" { continue } - tag = strings.Split(tag, ",")[0] - if tag == "" { + name, opt, _ := strings.Cut(tag, ",") + if name == "" { continue } field := v.Field(i) + + // miss field + if omitEmpty(opt) && isEmptyValue(field) { + continue + } + if field.CanInterface() { - dst = append(dst, tag, field.Interface()) + dst = append(dst, name, field.Interface()) } } return dst } +func omitEmpty(opt string) bool { + for opt != "" { + var name string + name, opt, _ = strings.Cut(opt, ",") + if name == "omitempty" { + return true + } + } + return false +} + +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Pointer: + return v.IsNil() + } + return false +} + type Cmdable interface { Pipeline() Pipeliner Pipelined(ctx context.Context, fn func(Pipeliner) error) ([]Cmder, error) diff --git a/commands_test.go b/commands_test.go index a667bf19..72b2bb23 100644 --- a/commands_test.go +++ b/commands_test.go @@ -2136,6 +2136,7 @@ var _ = Describe("Commands", func() { Set3 time.Duration `redis:"set3"` Set4 interface{} `redis:"set4"` Set5 map[string]interface{} `redis:"-"` + Set6 string `redis:"set6,omitempty"` } hSet = client.HSet(ctx, "hash", &set{ @@ -2148,13 +2149,29 @@ var _ = Describe("Commands", func() { Expect(hSet.Err()).NotTo(HaveOccurred()) Expect(hSet.Val()).To(Equal(int64(4))) - hMGet := client.HMGet(ctx, "hash", "set1", "set2", "set3", "set4") + hMGet := client.HMGet(ctx, "hash", "set1", "set2", "set3", "set4", "set5", "set6") Expect(hMGet.Err()).NotTo(HaveOccurred()) Expect(hMGet.Val()).To(Equal([]interface{}{ "val1", "1024", strconv.Itoa(int(2 * time.Millisecond.Nanoseconds())), "", + nil, + nil, + })) + + hSet = client.HSet(ctx, "hash2", &set{ + Set1: "val2", + Set6: "val", + }) + Expect(hSet.Err()).NotTo(HaveOccurred()) + Expect(hSet.Val()).To(Equal(int64(5))) + + hMGet = client.HMGet(ctx, "hash2", "set1", "set6") + Expect(hMGet.Err()).NotTo(HaveOccurred()) + Expect(hMGet.Val()).To(Equal([]interface{}{ + "val2", + "val", })) })