猿问

为什么切片有时通过引用传递,有时通过指针传递?

在container/heapgo的默认包中,有一个实现优先级队列的例子。


在查看示例代码时,它使用了一个切片[]*Item,并实现了heap.Interface.


我的问题是下面的一点。为什么某些函数将优先级队列声明为切片,有时将其声明为指向切片的指针?:


func (pq PriorityQueue) Swap(i, j int) {...}

// vs

func (pq *PriorityQueue) Push(x interface{}) {...}

为什么不总是这样(pq PriorityQueue)?在另一个关于指向切片的指针的 StackOverflow 线程上,文档说切片是引用类型,那么为什么要在它们上使用指针呢?我遇到了麻烦,因为官方文档说了些什么然后将两者混合在一起,而没有解释添加指针的意义。


感谢您的见解!


编辑:这是一个例子:


// original sample code from the docs:

func (pq *PriorityQueue) Push(x interface{}) {

    n := len(*pq)

    item := x.(*Item)

    item.index = n

    *pq = append(*pq, item)

}


// is this the same (removed pointers to slice) ?

func (pq PriorityQueue) Push(x interface{}) {

    n := len(pq)

    item := x.(*Item)

    item.index = n

    pq = append(pq, item)

}

如果两个函数相同,为什么现在使用指针?


慕雪6442864
浏览 252回答 1
1回答

慕斯王

Go 博客上的这篇文章解释了原因。从将切片传递给函数部分:即使切片包含一个指针,它本身也是一个值,理解这一点很重要。在幕后,它是一个包含指针和长度的结构值。它不是指向结构的指针。因此,您要么需要传递一个指针,要么需要将切片作为值返回,如果您想使用 append 修改它。如果您只想修改切片的内容,您可以简单地按值传递切片:尽管切片头是按值传递的,但头包含一个指向数组元素的指针,因此原始切片头和传递给函数的头的副本描述了相同的数组。因此,当函数返回时,可以通过原始切片变量看到修改后的元素。使用 append 您正在修改切片标头。和因此如果我们想写一个修改头的函数,我们必须将它作为结果参数返回或者:让函数修改切片头的另一种方法是传递一个指向它的指针。
随时随地看视频慕课网APP

相关分类

Go
我要回答