我会像其他人一样回答你的问题。但是,并不是说您尝试解决的问题最好通过循环一系列值来解决。继续阅读:
解决您的问题
就像其他人所说的那样,for-range
在值的范围内提供不可变的迭代。这意味着您对迭代中提供的值所做的任何更改都将丢失。它基本上是给你一个真实价值的副本,而不是实际价值。
for _, item := range box.BoxItems {
// ^-not the real `item`, it's a copy!
解决此问题的一种方法是跟踪 中的索引值for idx, val := range
,并使用它idx
来直接查找您要查找的值。
如果您更改 for 循环以保留索引值:
for i, item := range box.BoxItems {
// ^-keep this
您将能够引用您循环的数组中的实际项目:
for i, item := range box.BoxItems {
// Here, item is a copy of the value at box.BoxItems[i]
if item.Id == boxItem.Id {
// Refer directly to an item inside the slice
box.BoxItems[i].Qty++
return box.BoxItems[i] // Need to return the actual one, not the copy
}
}
操场
I would favor this approach over the for i; i<Len; i++
one as I find it more readable. But this is simply a matter of taste and the for i
form will be more efficient (beware of premature-optimization!).
Your real problem is
What you're trying to do is to avoid duplicating BoxItems
if their Id
already exists. To do this, you iterate over the whole range of the box.BoxItems
slice. If you have N
items in your box.BoxItems
slice, you will potentially iterate over all N
items before finding out that the item you're looking for doesn't exist! Basically, this means your algorithm is O(N).
If you increment Id
in natural order
That is, 0, 1, 2, 3, ..., n - 1, n
, you can keep using a slice to index your box items. You would do like this:
func (box *Box) AddBoxItem(boxItem BoxItem) BoxItem {
// Lookup your item by Id
if boxItem.Id < len(box.BoxItems) {
// It exists, do don't create it, just increment
item := box.BoxItems[boxItem.Id]
item.Qty++
box.BoxItems[boxItem.Id] = item
return item
}
// New item so append
box.BoxItems = append(box.BoxItems, boxItem)
return boxItem
}
Playground
If you increment Id
in any order
You should use a datastructure that offers fast lookups, such as the built-in map
, which offers O(1) lookups (that means, you need to do a single operation to find your item, not n
operations).
type Box struct {
BoxItems map[int]BoxItem
}
func (box *Box) AddBoxItem(boxItem BoxItem) BoxItem {
// Lookup the map by Id
item, ok := box.BoxItems[boxItem.Id]
if ok {
// It exists, do don't create it, just increment
item.Qty++
} else {
item = boxItem
}
// New item so add it to the map
box.BoxItems[boxItem.Id] = item
return item
}
Playground
This is a more correct way to solve your problem.