删除结构中切片的元素 [英] Remove an element of a slice in a struct

查看:73
本文介绍了删除结构中切片的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个结构"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()返回)分配给原始Guestfriends字段,该切片值的长度将减小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中使用selfthis之类的接收器名称不是惯用的,而是可以使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆