问题
I have an account struct as below:
type Account struct {
Id string
Name string
Address string
City string
Email string
Phone string
Username string
Password string
IsActive bool
}
I also have two function: find
and update
. The find
function find certain element from the slice and return the pointer to the element:
func find(accounts []Account, username string) *Account {
for _, acc := range accounts {
if acc.IsActive && acc.Username == username {
return &acc
}
}
return nil
}
The update function change certain field from the params:
func update(account *Account, name string) {
account.Name = name
}
In main
, i try to find
an element from the slice and store it to a pointer of account. Then, i try to update
a field in the next line. This is how my main
looks like:
func main() {
accounts := []Account{{
Id: "1",
Name: "name",
Address: "address",
City: "city",
Email: "email@email.com",
Phone: "123456789",
Username: "username",
Password: "1234",
IsActive: true,
}}
var acc *Account
acc = find(accounts, "username")
fmt.Printf("%v\n", accounts)
fmt.Println(acc)
update(acc, "updated")
fmt.Printf("%v\n", accounts)
fmt.Println(acc)
}
The problem is when update
called, the element in slice is not updated. It just update the data of stored account. Below is the output of main:
// find
[{1 name address city email@email.com 123456789 username 1234 true}]
&{1 name address city email@email.com 123456789 username 1234 true}
// update
[{1 name address city email@email.com 123456789 username 1234 true}]
&{1 updated address city email@email.com 123456789 username 1234 true}
How to make the element inside the slice updated when the store element changed? Thank you for your help, any suggestion would be appreciate.
回答1:
issue is you are returning copy of element rather than actual address of the element in the array
return &acc
change your find function as below
func find(accounts []Account, username string) *Account {
for idx , acc := range accounts {
if acc.IsActive && acc.Username == username {
return &accounts[idx]
}
}
return nil
}
your will get the expected response
[{1 name address city email@email.com 123456789 username 1234 true}]
&{1 name address city email@email.com 123456789 username 1234 true}
[{1 updated address city email@email.com 123456789 username 1234 true}]
&{1 updated address city email@email.com 123456789 username 1234 true}
you can check the updated code here in go playground
回答2:
in this code,
func find(accounts []Account, username string) *Account {
for _, acc := range accounts {
if acc.IsActive && acc.Username == username {
return &acc
}
}
return nil
}
Because the slice you are iterating is of type []Account
, each acc
value you get is a copy of the value stored in the slice.
Thus, the acc
value you are referencing is not the value stored in your slice.
To prevent that behavior, use a slice of pointer, ie: []*Account
.
Refrain from referencing the slice index as demonstrated in this play, you will run into bugs. https://play.golang.org/p/orgA8nCw2yc
来源:https://stackoverflow.com/questions/65095052/slice-element-not-updated-in-go