From 600f1665a0b58e69a81a1b4e29e2bd76b574e946 Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Wed, 3 Feb 2021 13:37:27 +0530 Subject: [PATCH] Add missing error checks and support for MGET in Scan() --- command.go | 22 +++++++++++++++++++--- example_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/command.go b/command.go index 642352c9..73194ecc 100644 --- a/command.go +++ b/command.go @@ -375,9 +375,21 @@ func (cmd *SliceCmd) String() string { // Scan scans the results from the map into a destination struct. The map keys // are matched in the Redis struct fields by the `redis:"field"` tag. func (cmd *SliceCmd) Scan(dest interface{}) error { - // Pass the list of keys and values. Skip the first to args (command, key), - // eg: HMGET map. - return hscan.Scan(cmd.args[2:], cmd.val, dest) + if cmd.err != nil { + return cmd.err + } + + // Pass the list of keys and values. + // Skip the first two args for: HMGET key + var args []interface{} + if cmd.args[0] == "hmget" { + args = cmd.args[2:] + } else { + // Otherwise, it's: MGET field field ... + args = cmd.args[1:] + } + + return hscan.Scan(args, cmd.val, dest) } func (cmd *SliceCmd) readReply(rd *proto.Reader) error { @@ -929,6 +941,10 @@ func (cmd *StringStringMapCmd) String() string { // Scan scans the results from the map into a destination struct. The map keys // are matched in the Redis struct fields by the `redis:"field"` tag. func (cmd *StringStringMapCmd) Scan(dest interface{}) error { + if cmd.err != nil { + return cmd.err + } + // Pass the list of keys and values. Skip the first to args (command, key), // eg: HGETALL map. var ( diff --git a/example_test.go b/example_test.go index 07eb5108..7d9f7405 100644 --- a/example_test.go +++ b/example_test.go @@ -310,6 +310,39 @@ func ExampleStringStringMapCmd_Scan() { // Output: {hello 123 true} } +// ExampleSliceCmd_Scan shows how to scan the results of a multi key fetch +// into a struct. +func ExampleSliceCmd_Scan() { + rdb.FlushDB(ctx) + err := rdb.MSet(ctx, + "name", "hello", + "count", 123, + "correct", true).Err() + if err != nil { + panic(err) + } + + res := rdb.MGet(ctx, "name", "count", "empty", "correct") + if res.Err() != nil { + panic(err) + } + + type data struct { + Name string `redis:"name"` + Count int `redis:"count"` + Correct bool `redis:"correct"` + } + + // Scan the results into the struct. + var d data + if err := res.Scan(&d); err != nil { + panic(err) + } + + fmt.Println(d) + // Output: {hello 123 true} +} + func ExampleClient_Pipelined() { var incr *redis.IntCmd _, err := rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {