我有一个结构“Guest”,其中包含一个聚会嘉宾的元数据(一个唯一的ID,姓名,姓氏以及作为该客人朋友的客人的唯一ID列表。
type Guest struct {
id int
name string
surname string
friends []int
}
我有以下代码从朋友列表中删除ID:
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
}
}
}
问题是:我要删除的元素会被元素的移位覆盖,但切片不会变短。而是将切片的最后一个元素相乘。
举个例子:guest1.friends
是[1,2,3,4,5]
。致电guest1.removeFriend(3)
后,结果为[1,2,4,5,5]
,而不是所需的[1,2,4,5]
。
那么,我做错了什么?
答案 0 :(得分:2)
任何想要/确实修改接收器的方法都必须使用指针接收器。
您的Guest.removeFriend()
方法确实尝试修改接收者(类型Guest
),即其friends
字段(切片类型),但由于您只使用了值接收器,您只是修改friends
副本的Guest
字段。原始Guest
值将具有未修改的切片值。
所以你必须使用指针接收器:
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)
输出(在Go Playground上尝试):
&{1 Bob Pats [1 2 3 4 5]}
&{1 Bob Pats [1 2 4 5]}
您在版本中看到切片是指向实际包含元素的数组的小结构描述符的解释。在您的示例中,您修改了支持数组的元素,因此具有原始切片的调用者将看到这些修改,但原始切片的大小将不会(不能)更改。
通过使用指针接收器,您将新切片值(由append()
返回)分配给原始friends
的{{1}}字段,切片值的长度将更小由1(由于1个被删除的元素)。
另请注意,在Go中使用Guest
和self
之类的接收者名称并非惯用,而是可以使用this
或guest
。