How to Implement a Queue in Go

Implement a circular queue in Go using a slice, a head index, and modulo arithmetic to manage fixed capacity efficiently.

Implement a queue in Go by wrapping a slice with a struct that tracks the head index and uses modulo arithmetic for circular behavior. This approach avoids expensive slice copying when removing elements.

package main

import "fmt"

type Queue[T any] struct {
  data []T
  head int
  size int
}

func NewQueue[T any](cap int) *Queue[T] {
  return &Queue[T]{data: make([]T, cap), head: 0, size: 0}
}

func (q *Queue[T]) Enqueue(v T) {
  if q.size == len(q.data) {
    panic("queue full")
  }
  tail := (q.head + q.size) % len(q.data)
  q.data[tail] = v
  q.size++
}

func (q *Queue[T]) Dequeue() (T, bool) {
  if q.size == 0 {
    var zero T
    return zero, false
  }
  v := q.data[q.head]
  q.head = (q.head + 1) % len(q.data)
  q.size--
  return v, true
}

func main() {
  q := NewQueue[int](5)
  q.Enqueue(1)
  q.Enqueue(2)
  v, ok := q.Dequeue()
  fmt.Println(v, ok) // 1 true
}