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

时间:2015-05-07 12:00:28

标签: pointers go

在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)
}

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

1 个答案:

答案 0 :(得分:5)

Go博客上的

This article解释了原因。

将切片传递给函数

部分
  

重要的是要理解即使切片包含一个   指针,它本身就是一个值。在封面下,它是一个结构值   拿着一个指针和一个长度。它不是指向结构的指针。

因此,您需要传递指针,或者如果要使用append修改它,则需要将切片作为值返回。

如果您只想修改切片的内容,只需按值传递切片:

  

即使切片标头按值传递,标头也包含一个   指向数组元素的指针,因此原始切片头和   传递给函数的头文件副本描述了相同的数组。   因此,当函数返回时,修改后的元素可以是   通过原始切片变量看到。

使用追加即可修改切片标头。和

  

因此,如果我们想编写一个修改标题的函数,我们必须这样做   将其作为结果参数返回

或者:

  

让函数修改切片标头的另一种方法是传递一个   指向它的指针。