diff --git a/internal/hscan/hscan.go b/internal/hscan/hscan.go index 203ec4aa..6ba66856 100644 --- a/internal/hscan/hscan.go +++ b/internal/hscan/hscan.go @@ -73,6 +73,9 @@ func Struct(dst interface{}) (StructValue, error) { // Scan scans the results from a key-value Redis map result set to a destination struct. // The Redis keys are matched to the struct's field with the `redis` tag. +// This method will attempt to unmarshal each field and will return an error if any of the +// fields cannot be unmarshalled. The destination struct will have the failed fields set to +// their zero value. func Scan(dst interface{}, keys []interface{}, vals []interface{}) error { if len(keys) != len(vals) { return errors.New("args should have the same number of keys and vals") @@ -83,6 +86,8 @@ func Scan(dst interface{}, keys []interface{}, vals []interface{}) error { return err } + scanErrors := []error{} + // Iterate through the (key, value) sequence. for i := 0; i < len(vals); i++ { key, ok := keys[i].(string) @@ -96,10 +101,14 @@ func Scan(dst interface{}, keys []interface{}, vals []interface{}) error { } if err := strct.Scan(key, val); err != nil { - return err + scanErrors = append(scanErrors, err) } } + if len(scanErrors) > 0 { + return fmt.Errorf("scan errors: %v", scanErrors) + } + return nil } diff --git a/internal/hscan/hscan_test.go b/internal/hscan/hscan_test.go index 6c9b3030..64639393 100644 --- a/internal/hscan/hscan_test.go +++ b/internal/hscan/hscan_test.go @@ -196,6 +196,22 @@ var _ = Describe("Scan", func() { Expect(Scan(&d, i{"bool"}, i{"123"})).To(HaveOccurred()) }) + It("does not stop scanning on first failure", func() { + var d data + + keys := i{"bool", "string", "int"} + vals := i{"-1", "foobar", "123"} + + err := Scan(&d, keys, vals) + Expect(err).To(HaveOccurred()) + + Expect(d).To(Equal(data{ + Bool: false, + String: "foobar", + Int: 123, + })) + }) + It("Implements Scanner", func() { var td TimeData