I have the following structs:
type Address struct {
Line1 string `firestore:"line1"`
City string `firestore:"city"`
}
type User struct {
Name string `firestore:"name,required"`
Email string `firestore:"email,required"`
Password string `firestore:"password,required"`
Address *Address `firestore:"address"`
Age int `firestore:"age,required"`
}
When I add a user doc to Firestore, everything works perfectly:
docRef, _, err := client.Collection("users").Add(ctx, User{
Name: "John",
Email: "jonh.doe@example.com",
Password: "123456",
Address: &Address{
Line1: "1 Main Road",
City: "NY",
},
Age: 18,
})
if err != nil {
fmt.Println(err)
} else {
fmt.Println(docRef.ID)
}
The problem is, when I try to fetch multiple users, using a query, and then converting them into User structs, using DataTo
method, the address field seems to be the same for all users - i.e. the same pointer has been used for all users...
var user User
var users []Users
iter := query.Documents(ctx)
for {
docSnap, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
fmt.Println(err)
}
err = docSnap.DataTo(&user)
if err != nil {
fmt.Println(err)
}
fmt.Println(user)
users = append(users, user)
}
fmt.Println(docs)
Am I doing something wrong?
I know this isn't an issue if I don't use a pointer for Address, but since some users may have a nil address, I find that using a pointer in this case is beneficial. Is this a bug, or is this how it's supposed to work?
The first call to docSnap.DataTo(&user)
sets user.Address
to a newly allocated Address
. Subsequent calls to DataTo
reuse that Address
. Fix by this and other potential issues by declaring user
inside the scope of the for loop.
var users []Users
iter := query.Documents(ctx)
for {
docSnap, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
fmt.Println(err)
}
var user User // <-- declare user here
err = docSnap.DataTo(&user)
if err != nil {
fmt.Println(err)
}
fmt.Println(user)
users = append(users, user)
}