问题
Problem:
append
inside Users()
for loop below adds the last item in users
3x into userRxs []*UserResolver
Expectation:
append
should add each item inside users
into userRxs []*UserResolver
// Users return all users from Db
func (r *RootResolver) Users() ([]*UserResolver, error) {
var userRxs []*UserResolver
users := r.Db.Users()
for _, u := range users {
log.Printf("userID: %s, username: %s, email: %s, password: %s", u.UserID, u.Username, u.Email, u.Password)
userRxs = append(userRxs, &UserResolver{&u})
}
log.Printf("%v", userRxs)
return userRxs, nil
}
inside the for loop, log.Printf
prints this
userID: 0374402a-3dc4-48da-86c4-949905ccc26c, username: sunnysan, email: sunnysan@gmail.com, password: 12345678
userID: 53f21c4f-2cd8-4e67-b3e9-5ef344806230, username: sunnysan2, email: sunnysan2@gmail.com, password: 12345678
userID: 0a47d3af-03dc-4050-a028-7a41599af497, username: sunnysan3, email: sunnysan3@gmail.com, password: 12345678
after the for loop, log.Printf("%v", userRxs)
prints this
[
User {
userID: 0a47d3af-03dc-4050-a028-7a41599af497,
username: sunnysan3,
email: sunnysan3@gmail.com,
password: 12345678
}
User {
userID: 0a47d3af-03dc-4050-a028-7a41599af497,
username: sunnysan3,
email: sunnysan3@gmail.com,
password: 12345678
}
User {
userID: 0a47d3af-03dc-4050-a028-7a41599af497,
username: sunnysan3,
email: sunnysan3@gmail.com,
password: 12345678
}
]
here's the entire file for more context
package main
import (
"fmt"
"log"
graphql "github.com/graph-gophers/graphql-go"
)
/*
* User GQL type
type User {
userID: ID!
username: String!
email: String!
password: String!
}
*/
// User type should match the exact shape of the schema commented above
type User struct {
UserID graphql.ID
Username string
Email string
Password string
}
// RootResolver ingests Db to run queries (getters) against it
type RootResolver struct {
*Db
}
// String prints pretty structs ie. fmt.Printf can't do it on its own
func (r *UserResolver) String() string {
return fmt.Sprintf("User{userID: %s, username: %s, email: %s, password: %+v}",
r.u.UserID, r.u.Username, r.u.Email, r.u.Password,
)
}
// Users return all users from Db
func (r *RootResolver) Users() ([]*UserResolver, error) {
var userRxs []*UserResolver
users := r.Db.Users()
for _, u := range users {
log.Printf("userID: %s, username: %s, email: %s, password: %s", u.UserID, u.Username, u.Email, u.Password)
userRxs = append(userRxs, &UserResolver{&u})
}
log.Printf("%v+", userRxs)
return userRxs, nil
}
// User returns a single user from Db
func (r *RootResolver) User(args struct{ UserID graphql.ID }) (*UserResolver, error) {
// Find user:
u, err := r.Db.User(args.UserID)
if err != nil {
// Didn’t find user:
return nil, nil
}
return &UserResolver{&u}, nil
}
// UserResolver ingests properties from User
type UserResolver struct{ u *User }
// UserID returns the userId of the user
func (r *UserResolver) UserID() graphql.ID {
return r.u.UserID
}
// Username returns the username of the user
func (r *UserResolver) Username() string {
return r.u.Username
}
// Email returns the email of the user
func (r *UserResolver) Email() string {
return r.u.Email
}
// Password returns the password of the user
func (r *UserResolver) Password() string {
return r.u.Password
}
r.Db.Users()
method
// Users correspond to Users query from graphql
func (d *Db) Users() []User {
rows, err := d.Query("SELECT * FROM users")
Check(err, "stmt.Query")
// Create User struct for holding each row's data
var r User
// Create slice of Users for our response
users := []User{}
// Copy the columns from row into the values pointed at by r (User)
// order matters here from db table
defer rows.Close()
for rows.Next() {
err = rows.Scan(
&r.UserID,
&r.Username,
&r.Email,
&r.Password,
)
Check(err, "rows.Next")
users = append(users, r)
}
return users
}
回答1:
The range variable is overwritten at each iteration, and &u
is the same. So you end up appending a UserResolver
containing the same address multiple times. You need to use a local copy of that variable. Try this:
for _, u := range users {
u:=u // Make a copy of the variable and redeclare it
userRxs = append(userRxs, &UserResolver{&u})
}
来源:https://stackoverflow.com/questions/61641558/golang-append-issue-inside-a-for-loop