在go中的默认container/heap
包中,有一个实现优先级队列的示例。
在查看the sample code时,它会使用切片[]*Item
,并实现heap.Interface
。
我的麻烦在于以下几点。为什么某些函数使用优先级队列作为切片声明,有时作为指向切片的指针?:
func (pq PriorityQueue) Swap(i, j int) {...}
// vs
func (pq *PriorityQueue) Push(x interface{}) {...}
为什么不总是(pq PriorityQueue)
?在另一个StackOverflow thread about pointer to slices上,文档说切片是refence类型,那么为什么要在它们上使用指针呢?我遇到了这样一个事实,即官方文档会说某些东西然后混合两者而不解释添加指针的点。
感谢您的见解!
修改: 这是一个例子:
// 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)
}
如果两个函数相同,为什么现在使用指针?
答案 0 :(得分:5)
This article解释了原因。
从将切片传递给函数
部分重要的是要理解即使切片包含一个 指针,它本身就是一个值。在封面下,它是一个结构值 拿着一个指针和一个长度。它不是指向结构的指针。
因此,您需要传递指针,或者如果要使用append修改它,则需要将切片作为值返回。
如果您只想修改切片的内容,只需按值传递切片:
即使切片标头按值传递,标头也包含一个 指向数组元素的指针,因此原始切片头和 传递给函数的头文件副本描述了相同的数组。 因此,当函数返回时,修改后的元素可以是 通过原始切片变量看到。
使用追加即可修改切片标头。和
因此,如果我们想编写一个修改标题的函数,我们必须这样做 将其作为结果参数返回
或者:
让函数修改切片标头的另一种方法是传递一个 指向它的指针。