0

I came across priorityqueue example under heap.Interface package

Link: https://golang.org/pkg/container/heap/#Interface

For Push() and Pop() function required by heap.Interface, the implementation is on pointer receiver. But for Swap() function required by sort.Interface, the implementation is on value.

Why this difference ?

As per my understanding, Push() and Pop() are implemented on pointer type, as they need to change the underlying data. But going by that logic, Swap() should also be implemented on pointer type.

How and why does the Swap() implementation work on value, but Push() and Pop() do not ?

Chinmay B
  • 427
  • 4
  • 7

3 Answers3

2

A pointer receiver is needed when the value passed needs to be modified. In the case of Swap, the value itself (which is a slice) doesn't get modified, although the array backing the slice does get modified.

In the case of Push and Pop, the slice does get modified since in both cases the length changes (and in the case of Push the underlying array may get replaced by a new one if it has reached its capacity).

Paul Hankin
  • 54,811
  • 11
  • 92
  • 118
2

Take a look at Push implementation:

func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)  // Here, the slice is assigned a new value
}

Push (and Pop) modify the underlying slice as well as the slice elements for the priority queue, whereas Swap will only swap two elements in the slice, and will not change the slice itself. Thus, Swap can work with a value receiver.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
2

Internally, a slice variable holds a length, a capacity, and a pointer to the data. Swapping items changes the data, but doesn't change any of the items in the slice header. Russ Cox explained this in a blog post.

Adding items to the slice, like to push something onto a heap, may require the array to be re-allocated, which will change the capacity and the location that needs to be pointed to.

You may find this answer on pointers vs. values generally to be useful. There are other types, like channels and maps, that contain references such that you don't need a pointer to mess with the data underneath.

twotwotwo
  • 28,310
  • 8
  • 69
  • 56