Skip to content
11 changes: 10 additions & 1 deletion internal/hscan/hscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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)
Expand All @@ -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
}

Expand Down
16 changes: 16 additions & 0 deletions internal/hscan/hscan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading