为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在实现 golang 类型的 sort.Interface 时方法接收器不需要是指针?

为什么在实现 golang 类型的 sort.Interface 时方法接收器不需要是指针?

Go
ABOUTYOU 2021-07-28 13:43:26
我正在阅读sort stdlib 包的文档,示例代码如下所示:type ByAge []Personfunc (a ByAge) Len() int           { return len(a) }func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }正如我所了解的,改变类型的函数T需要*T用作其方法接收器。在的情况下Len,Swap以及Less为什么它的工作原理?还是我误解了 usingT与*Tas 方法接收器之间的区别?
查看完整描述

2 回答

?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

Go 有三种引用类型:

  • 地图

  • 渠道

这些类型的每个实例都在内部持有一个指向实际数据的指针。这意味着当您传递这些类型之一的值时,该值会像其他所有值一样被复制,但内部指针仍指向相同的值。

快速示例(在游戏中运行):

func dumpFirst(s []int) {

    fmt.Printf("address of slice var: %p, address of element: %p\n", &s, &s[0])

}


s1 := []int{1, 2, 3}

s2 := s1


dumpFirst(s1)

dumpFirst(s2)

将打印如下内容:


address of slice var: 0x1052e110, address of element: 0x1052e100

address of slice var: 0x1052e120, address of element: 0x1052e100

您可以看到:切片变量的地址发生了变化,但该切片中第一个元素的地址保持不变。


查看完整回答
反对 回复 2021-08-02
?
阿晨1998

TA贡献2037条经验 获得超6个赞

关于这个完全相同的问题,我刚刚有了一个小小的顿悟。

正如已经解释过的,类型化切片(不是指向切片的指针)可以实现该sort.Interface接口;部分原因是,即使切片正在被复制,其字段之一是指向数组的指针,因此对该后备数组的任何修改都将反映在原始切片中。

但是,通常情况下,这不足以证明裸片成为可接受的接收器。尝试将结构体修改为方法的接收者通常是不正确的,因为任何append()调用都会更改切片副本的长度,而不会修改原始切片的标头。切片修改甚至可能触发新后备阵列的初始化,从而完全断开复制的接收器与原始切片的连接。

然而,就排序的本质而言,在这种sort.Sort情况下这不是问题。它执行的唯一数组修改操作是Swap,这意味着数组所需的内存将保持不变,因此切片不会改变大小,因此切片的实际值(起始索引、长度和数组指针)不会发生变化.

我相信这对很多人来说都是显而易见的,但我才突然明白,我认为这可能对其他人有用,因为他们想知道为什么用sort裸片很好地演奏。


查看完整回答
反对 回复 2021-08-02
  • 2 回答
  • 0 关注
  • 190 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信