I want to make a min and max heap of integers:
package main
import (
"container/heap"
"fmt"
)
func main() {
hi := make(IntHeap, 0)
for number := 10; number >= 0; number-- {
hi = append(hi, number)
}
heap.Init(&hi)
fmt.Println(heap.Pop(&hi))
fmt.Println(heap.Pop(&hi))
fmt.Println(heap.Pop(&hi))
}
// An IntHeap is a min-heap of ints.
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
type IntMaxHeap IntHeap
func (h IntMaxHeap) Less(i, j int) bool { return h[i] > h[j] }
If I want to use IntMaxHeap
instead, I am getting:
./median_stream.go:14: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:15: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:16: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
./median_stream.go:17: cannot use &hi (type *IntMaxHeap) as type heap.Interface in function argument:
*IntMaxHeap does not implement heap.Interface (missing Len method)
How can I make two structs ("classes") which differ with just one method implementation? The working version should print 3 biggest numbers from the heap.
When you declare a new type in Go, it doesn't inherit the methods of the underlying type. If you do want to inherit methods, consider using composition:
type IntMaxHeap struct {
IntHeap
}
func (h IntMaxHeap) Less(i, j int) bool { return h.IntHeap[i] > h.IntHeap[j] }
If you have a primed IntHeap
(or any []int
slice, for that matter), you can construct this type with IntMaxHeap{slice}
without needing to reimplement the other methods.
This pattern can be quite useful to declare multiple orderings for use with the sort
package, without duplicating methods.
Short answer: you can't. Go has no method inheritance. The shortest you could get is by using anonymous fields (see the spec about struct types), but you will lose the slice mechanics.
You will have to re-implement the interface for each type. But you can do it smartly, by using an unexported function to do the job, and just return the result of this function. That could save you a few typing and ensure your methods have the same inner workings.
Example:
type A []int
func (a A) Len() int {
return getLen(a)
}
type B []int
func (b B) Len() int {
return getLen(a)
}
func getLen(slice []int) int {
return len(slice)
}
Obviously my example is dumb, because I'm just wrapping the len
built-in, but for longer functions (say, other that oneliners), it is quite useful.