我有一个结构“ 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]。
guest1.friends
[1,2,3,4,5]
guest1.removeFriend(3)
[1,2,4,5,5]
[1,2,4,5]
那么,我在做什么错呢?
任何打算/确实修改接收器的方法都必须使用指针接收器。
您的Guest.removeFriend()方法确实尝试修改接收器(类型Guest),即其friends字段(属于切片类型),但是由于您仅使用了值接收器,因此您仅在修改副本的friends字段Guest。原始Guest值将具有未修改的切片值。
Guest.removeFriend()
Guest
friends
因此,您 必须 使用指针接收器:
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]}
关于在您的版本中看到的内容的说明,切片是指向实际包含元素的数组的小型结构描述符。在您的示例中,您修改了backing数组的元素,因此具有原始切片的调用方将看到这些修改,但是原始切片的大小不会(无法)改变。
通过使用指针接收器,您会将新的切片值(由返回append())分配给friends原始字段Guest,切片值的长度将减小1(由于删除了1个元素)。
append()
另外请注意,在Go中使用诸如self和的接收者名称this不是惯用语,而是可以使用guest或g。
self
this
guest
g