dsedug8644 2017-11-22 12:48
浏览 34
已采纳

删除结构中切片的元素[重复]

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
}

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.

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?

</div>
  • 写回答

1条回答 默认 最新

  • dow46218 2017-11-22 12:51
    关注

    Any method that intends / does modify the receiver must use a pointer receiver.

    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) {
        // ...
    }
    

    Testing it:

    g := &Guest{
        id:      1,
        name:    "Bob",
        surname: "Pats",
        friends: []int{1, 2, 3, 4, 5},
    }
    
    fmt.Println(g)
    g.removeFriend(3)
    fmt.Println(g)
    

    Output (try it on the Go Playground):

    &{1 Bob Pats [1 2 3 4 5]}
    &{1 Bob Pats [1 2 4 5]}
    

    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.

    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).

    Also note that in Go using receiver names like self and this is not idiomatic, instead you could use guest or simply g.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥30 python代码,帮调试,帮帮忙吧
  • ¥15 #MATLAB仿真#车辆换道路径规划