diff --git a/commands_test.go b/commands_test.go index 7e0182f0..fdc3452c 100644 --- a/commands_test.go +++ b/commands_test.go @@ -1900,6 +1900,25 @@ var _ = Describe("Commands", func() { Key2: 123, Time: TimeValue{Time: time.Time{}}, })) + + type data2 struct { + Key1 string `redis:"key1"` + Key2 int `redis:"key2"` + Time time.Time `redis:"time"` + } + err = client.HSet(ctx, "hash", &data2{ + Key1: "hello2", + Key2: 200, + Time: now, + }).Err() + Expect(err).NotTo(HaveOccurred()) + + var d2 data2 + err = client.HMGet(ctx, "hash", "key1", "key2", "time").Scan(&d2) + Expect(err).NotTo(HaveOccurred()) + Expect(d2.Key1).To(Equal("hello2")) + Expect(d2.Key2).To(Equal(200)) + Expect(d2.Time.Unix()).To(Equal(now.Unix())) }) It("should HIncrBy", func() { diff --git a/internal/hscan/hscan_test.go b/internal/hscan/hscan_test.go index 9d6df01b..728ffad0 100644 --- a/internal/hscan/hscan_test.go +++ b/internal/hscan/hscan_test.go @@ -200,4 +200,16 @@ var _ = Describe("Scan", func() { Expect(td.Time.UnixNano()).To(Equal(now.UnixNano())) Expect(td.Time.Format(time.RFC3339Nano)).To(Equal(now.Format(time.RFC3339Nano))) }) + + It("should time.Time RFC3339Nano", func() { + type TimeTime struct { + Time time.Time `redis:"time"` + } + + now := time.Now() + + var tt TimeTime + Expect(Scan(&tt, i{"time"}, i{now.Format(time.RFC3339Nano)})).NotTo(HaveOccurred()) + Expect(now.Unix()).To(Equal(tt.Time.Unix())) + }) }) diff --git a/internal/hscan/structmap.go b/internal/hscan/structmap.go index 9befd987..8d6028ef 100644 --- a/internal/hscan/structmap.go +++ b/internal/hscan/structmap.go @@ -1,10 +1,13 @@ package hscan import ( + "encoding" "fmt" "reflect" "strings" "sync" + + "github.com/redis/go-redis/v9/internal/util" ) // structMap contains the map of struct fields for target structs @@ -97,8 +100,11 @@ func (s StructValue) Scan(key string, value string) error { } if isPtr && v.Type().NumMethod() > 0 && v.CanInterface() { - if scan, ok := v.Interface().(Scanner); ok { + switch scan := v.Interface().(type) { + case Scanner: return scan.ScanRedis(value) + case encoding.TextUnmarshaler: + return scan.UnmarshalText(util.StringToBytes(value)) } }