Home >Backend Development >Golang >Unmarshalling dynamodb projects returns the same project
php editor Zimo will introduce to you today how to solve the problem of ungrouping DynamoDB items and returning the same items. DynamoDB is a high-performance, serverless key-value database, but sometimes it may return the same items when querying them, which can be a tricky problem for developers. Don't worry, we'll provide you with a solution to ensure your query results are unique and correct. In this article, we will explain the cause of the problem in detail and provide a simple and effective way to solve it. Let’s take a look!
I have a range loop in golang that loops through the mapping of type.attributevalues
returned by dynamodb using a scan function.
I'm looping through this map using the built-in function provided by the golang aws-sdk-v2 package attributevalue.unmarshalmap()
and what happens is that I get back items that are the same length as the slice.
Code:
type users struct { user *string `dynamodbav:"user"` email *string `dynamodbav:"email"` } user := users{} for _ , dbitem := range dynamoresults.items { err = attributevalue.unmarshalmap(dbitem, &user) } // gives the same pointer location for all users[0].user users[1].user users[2].user
I also tried appending the user to the slice in the results
// this just gives a slice with the same items as above u := []Users{} for _ , dbItem := range dynamoResults.Items { err = attributevalue.UnmarshalMap(dbItem, &Users) u = append(u, Users) }
The solution I found using attributevalue.unmarshallistofmaps()
is to simply provide the function with a slice of items from dynamodb.
My question is actually to understand why using the above two solutions doesn't work as expected, doesn't it loop through the dynamodb items and pass them individually to the unmarshal function? It seems like just keep doing the same thing.
If we change the problem slightly - from dynamo db unmarshalling to json unmarshalling - then we can go playground. In the sample code, I see two factors working together to cause duplicate slice values:
The unmarshalling target is defined outside the loop (line 51), so when unmarshalling u1out
, the result is written to the same location on each loop iteration (line 54) .
user1
is *string
, so when the loop variable value is copied to the slice (line 55), user
and email
The string pointed to will not be copied. Only their pointer values are copied.
Putting these two together, each iteration will write the unmarshaled user
and email
values to the same memory location. This is demonstrated by the first two lines of output, which print the elements of u1out
.
The remaining lines of output show the results in three other cases: when the target variable is moved within the loop (u1in
and u2in
) or when the field is changed to string
(u2out
). In each case, new locations for ungrouped values are created as expected, and duplicates are not printed.
package main import ( "encoding/json" "fmt" ) type ( Users1 struct { User *string Email *string } Users2 struct { User string Email string } ) func main() { dbItems := []string{ `{"User":"userA","Email":"<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="a7d2d4c2d5e6e7c2dfc6cad7cbc289c4c8ca">[email protected]</a>"}`, `{"User":"userB","Email":"<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="5a2f293f28181a3f223b372a363f74393537">[email protected]</a>"}`, } u1Out := withVarDeclaredOutsideLoop[Users1](dbItems) printUsers(u1Out) u1In := withVarDeclaredInsideLoop[Users1](dbItems) printUsers(u1In) u2Out := withVarDeclaredOutsideLoop[Users2](dbItems) printUsers(u2Out) u2In := withVarDeclaredInsideLoop[Users2](dbItems) printUsers(u2In) // Output // u[0] = {User:0xc000014130 Email:0xc000014140} // u[1] = {User:0xc000014130 Email:0xc000014140} // u[0] = {User:0xc0000141c0 Email:0xc0000141d0} // u[1] = {User:0xc000014210 Email:0xc000014220} // u[0] = {User:userA Email:<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="86f3f5e3f4c7c6e3fee7ebf6eae3a8e5e9eb">[email protected]</a>} // u[1] = {User:userB Email:<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="07727462754547627f666a776b622964686a">[email protected]</a>} // u[0] = {User:userA Email:<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="98edebfdead9d8fde0f9f5e8f4fdb6fbf7f5">[email protected]</a>} // u[1] = {User:userB Email:<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="fe8b8d9b8cbcbe9b869f938e929bd09d9193">[email protected]</a>} } func withVarDeclaredOutsideLoop[T any](dbItems []string) []T { var t T u := []T{} for _, dbItem := range dbItems { json.Unmarshal([]byte(dbItem), &t) u = append(u, t) } return u } func withVarDeclaredInsideLoop[T any](dbItems []string) []T { u := []T{} for _, dbItem := range dbItems { var t T json.Unmarshal([]byte(dbItem), &t) u = append(u, t) } return u } func printUsers[T any](u []T) { for i, user := range u { fmt.Printf("u[%d] = %+v\n", i, user) } }
The above is the detailed content of Unmarshalling dynamodb projects returns the same project. For more information, please follow other related articles on the PHP Chinese website!