go 64 lines · 9 steps

A priority job queue with Go's container/heap

Implementing heap.Interface turns a slice of jobs into a priority queue ordered by priority then arrival time.

Explained by highlit
1package scheduler
2 
3import (
4 "container/heap"
5 "time"
6)
7 
8type Job struct {
9 ID string
10 Priority int
11 Enqueued time.Time
12 Payload []byte
13 index int
14}
15 
16type JobQueue []*Job
17 
18func (q JobQueue) Len() int { return len(q) }
19 
20func (q JobQueue) Less(i, j int) bool {
21 if q[i].Priority != q[j].Priority {
22 return q[i].Priority > q[j].Priority
23 }
24 return q[i].Enqueued.Before(q[j].Enqueued)
25}
26 
27func (q JobQueue) Swap(i, j int) {
28 q[i], q[j] = q[j], q[i]
29 q[i].index = i
30 q[j].index = j
31}
32 
33func (q *JobQueue) Push(x any) {
34 job := x.(*Job)
35 job.index = len(*q)
36 *q = append(*q, job)
37}
38 
39func (q *JobQueue) Pop() any {
40 old := *q
41 n := len(old)
42 job := old[n-1]
43 old[n-1] = nil
44 job.index = -1
45 *q = old[:n-1]
46 return job
47}
48 
49func (q *JobQueue) Enqueue(job *Job) {
50 job.Enqueued = time.Now()
51 heap.Push(q, job)
52}
53 
54func (q *JobQueue) Dequeue() (*Job, bool) {
55 if q.Len() == 0 {
56 return nil, false
57 }
58 return heap.Pop(q).(*Job), true
59}
60 
61func (q *JobQueue) Reprioritize(job *Job, priority int) {
62 job.Priority = priority
63 heap.Fix(q, job.index)
64}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Satisfying heap.Interface lets the standard library manage ordering while you own the storage.
  2. 2A tie-breaker in Less gives you stable, fair ordering — here oldest job wins on equal priority.
  3. 3Tracking each element's index enables O(log n) removal and reprioritization, not just push and pop.

Related explainers

Share this explainer

Here's the card — post it anywhere.

A priority job queue with Go's container/heap — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code