切片元素未在 go 中更新

Slice element not updated in go

我的账户结构如下:

type Account struct {
    Id       string
    Name     string
    Address  string
    City     string
    Email    string
    Phone    string
    Username string
    Password string
    IsActive bool
}

我还有两个函数:findupdatefind 函数从切片中找到某个元素,return 指向该元素的指针:

func find(accounts []Account, username string) *Account {
    for _, acc := range accounts {
        if acc.IsActive && acc.Username == username {
            return &acc
        }
    }
    return nil
}

更新函数更改参数中的某些字段:

func update(account *Account, name string) {
    account.Name = name
}

main中,我尝试find切片中的一个元素并将其存储到帐户的指针中。然后,我尝试 update 下一行中的一个字段。这就是我的 main 的样子:

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)
}

问题是调用update时,切片中的元素没有更新。它只是更新存储帐户的数据。以下是 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}

如何在store元素改变的时候更新slice里面的元素?感谢您的帮助,如有任何建议,我们将不胜感激。

在您的代码中,

func find(accounts []Account, username string) *Account {
    for _, acc := range accounts {
        if acc.IsActive && acc.Username == username {
            return &acc
        }
    }
    return nil
}

因为您正在迭代的切片是 []Account 类型,所以您获得的每个 acc 值都是存储在切片中的值的副本。 因此,您引用的 acc 值不是存储在切片中的值。

要防止这种行为,请使用指针切片,即:[]*Account

避免引用您接受的答案中演示的切片索引,您可能 运行 进入微妙之处,再次使用 []*Account

https://play.golang.org/p/ru_0v_z8E9l

package main

import (
    "fmt"
)

type Account struct {
    Id       string
    Name     string
    Address  string
    City     string
    Email    string
    Phone    string
    Username string
    Password string
    IsActive bool
}

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.Println("the original data")
    fmt.Printf("%#v\n", accounts)
    fmt.Printf("%#v\n", acc)

    fmt.Println()
    fmt.Println("lets update the value pointed at the first position in the slice")
    update(acc, "updated")
    fmt.Printf("%#v\n", accounts)
    fmt.Printf("%#v\n", acc)
    fmt.Println("the item is updated in both variable, we are god so far.")

    fmt.Println()
    fmt.Println("increasing the length of the slice to force a backing array update")
    accounts = append(accounts, Account{})
    accounts = append(accounts, Account{})
    accounts = append(accounts, Account{}) // ensure append function changes the backing array

    fmt.Println()
    fmt.Println("now lets update that f pointer again")
    update(acc, "updated again") // update again
    fmt.Printf("%#v\n", accounts)
    fmt.Printf("%#v\n", acc)
    fmt.Println("Have you spotted the issue in the Account slice at position 0 ?")
    fmt.Println()
    fmt.Println(`In regard to OP question: How to make the element inside the slice updated when the store element changed?`)
    fmt.Println("it is a use case that fails")
}
func find(accounts []Account, username string) *Account {
    for i, acc := range accounts {
        if acc.IsActive && acc.Username == username {
            return &accounts[i]
        }
    }
    return nil
}
func update(account *Account, name string) {
    account.Name = name
}

问题是您返回的是元素的副本而不是数组中元素的实际地址

return &acc

如下更改查找功能

func find(accounts []Account, username string) *Account {
for idx , acc := range accounts {
    if acc.IsActive && acc.Username == username {
        return &accounts[idx]
    }
}
return nil
}

你会得到预期的回应

[{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}

您可以查看更新后的代码here in go playground