Closed renbou closed 1 year ago
I have the same problem as well... I wasted a whole day on it since I can't imagine that this method would have such a serious yet obvious BUG!!!!!
Any way, I have found a tricky way to solve it, but not perfect: marshal to json first, and then unmarshal back to my struct.
if err := result.Iterate(func(doc types.Document) error {
bytes, err := doc.MarshalJSON()
if err != nil {
return err
}
data := new(T)
if err := json.Unmarshal(bytes, data); err != nil {
return err
}
// fmt.Println("DataBefore", data)
// if err := document.StructScan(doc, data); err != nil {
// return nil
// }
fmt.Println("DataAfter", data)
datas = append(datas, data)
return nil
}); err != nil {
return nil, err
}
However, I think scanValue should make an deepcopy from the underlying data, in order to solve the problem complete.
func StructScan(doc types.Document, data interface{}) error {
bytes, err := doc.MarshalJSON()
if err != nil {
return err
}
return json.Unmarshal(bytes, data)
}
This is indeed a bug in StructScan. The iteration itself works as expected and only copies data when needed, but StructScan should definitely create a deep copy. I'll publish a fix this week.
Is there a fix for this issue @asdine? thanks.
What version of Genji are you using?
Genji v0.15.1
What did you do?
Scanning documents during iteration (either inside Result.Iterate manually, or using document.ScanIterator) results in invalid, "broken" documents after the iteration is finished. That is, during iteration, the results are valid, however, after the scan is complete, the scanned items are completely broken. Well, at least the strings, that is, since it seems like they are directly converted from some underlying []byte slice, which is why their content changes after the scan.
Here's an example of the bug on the latest version: https://go.dev/play/p/qRKyf_jRqlR
What did you expect to see?
Expected the value during iteration and after iteration to be equal to
main.item{A:2, B:"sample text 2"}
.What did you see instead?
During iteration the value is, indeed, scanned correctly as
main.item{A:2, B:"sample text 2"}
. After iteration, however, its contents change tomain.item{A:2, B:"sample text 1"}
.