删除结构中切片的元素 [英] Remove an element of a slice in a struct
问题描述
我有一个结构"Guest",其中包含聚会客人的元数据(唯一的ID,姓名,姓氏以及作为该客人的朋友的客人的唯一ID的列表.
I have a struct "Guest" which contains metadata of a party guest (a unique ID, name, surname and a list of the unique IDs of the guests who are friends of this guest.
type Guest struct {
id int
name string
surname string
friends []int
}
我有以下代码从朋友列表中删除ID:
I have the following code to remove an ID from the list of friends:
func (self Guest) removeFriend(id int) {
for i, other := range self.friends {
if other == id {
self.friends = append(self.friends[:i], self.friends[i+1:]...)
break
}
}
}
问题是:我要删除的元素被元素的移位覆盖,但是切片不会变短.而是将切片的最后一个元素相乘.
The problem is: The element I want to remove is overwritten by the shift of the elements, but the slice does not get shorter. Instead, the last element of the slice is multiplied.
举个例子:guest1.friends
是[1,2,3,4,5]
.呼叫guest1.removeFriend(3)
后,结果是[1,2,4,5,5]
而不是所需的[1,2,4,5]
.
To give an example: guest1.friends
is [1,2,3,4,5]
. After I call guest1.removeFriend(3)
, the result is [1,2,4,5,5]
instead of the desired [1,2,4,5]
.
那么,我在做什么错了?
So, what am I doing wrong?
推荐答案
任何打算/确实修改接收方的方法都必须使用指针接收方.
Any method that intends / does modify the receiver must use a pointer receiver.
您的Guest.removeFriend()
方法确实尝试修改接收器(类型为Guest
),即其friends
字段(属于切片类型),但是由于您仅使用了值接收器,因此您仅修改了Guest
副本的friends
字段.原始的Guest
值将具有未修改的切片值.
Your Guest.removeFriend()
method indeed tries to modify the receiver (of type Guest
), namely its friends
field (which is of slice type), but since you only used a value receiver, you are only modifying the friends
field of a Guest
copy. The original Guest
value will have the unmodified slice value.
因此,您必须使用指针接收器:
So you must use a pointer receiver:
func (self *Guest) removeFriend(id int) {
// ...
}
测试:
g := &Guest{
id: 1,
name: "Bob",
surname: "Pats",
friends: []int{1, 2, 3, 4, 5},
}
fmt.Println(g)
g.removeFriend(3)
fmt.Println(g)
输出(在游乐场上尝试):
&{1 Bob Pats [1 2 3 4 5]}
&{1 Bob Pats [1 2 4 5]}
在您的版本中看到的解释是,切片是小型结构描述符,指向实际包含元素的数组.在您的示例中,您修改了backing数组的元素,因此具有原始切片的调用方将看到这些修改,但是原始切片的大小不会(无法)更改.
The explanation for what you see in your version that slices are small struct descriptors pointing to an array that actually holds the elements. In your example you modified the elements of the backing array, so the caller having the original slice will see those modifications, but the size of the original slice will not (cannot) change.
通过使用指针接收器,您会将新的切片值(由append()
返回)分配给原始Guest
的friends
字段,该切片值的长度将减小1(由于1个已删除的元素).
By using a pointer receiver, you will assign the new slice value (returned by append()
) to the friends
field of the original Guest
, the slice value whose length will be smaller by 1 (due to the 1 removed element).
还请注意,在Go中使用self
和this
之类的接收器名称不是惯用的,而是可以使用guest
或简单地使用g
.
Also note that in Go using receiver names like self
and this
is not idiomatic, instead you could use guest
or simply g
.
这篇关于删除结构中切片的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!