HowtoGo
Home / Data Structures / Data Structures in Go
Data Structures

Data Structures in Go

Go gives you a small set of built-in structures — arrays, slices, maps, structs — and lets you build everything else, like trees, heaps, and graphs, on top of them.

Data structure reference

StructureDescriptionReal-world example
ArrayFixed-length, fixed-type sequence.RGB pixel buffer of a fixed image size
SliceGrowable view over a backing array.Loading rows from a database query
MapHash table of key-value pairs.Caching HTTP responses by URL
StructNamed fields grouped into one record.A user profile with name, email, age
Linked list (singly)Nodes chained by one forward pointer.A music player's next-track chain
Linked list (doubly)Nodes chained forward and backward.Browser back/forward navigation history
StackLast in, first out access.Undo history in a text editor
QueueFirst in, first out access.A print spooler processing jobs in order
Binary search treeOrdered tree, O(log n) lookup when balanced.Autocomplete suggestions sorted alphabetically
HeapTree keeping the min or max at the root.A task scheduler running the highest-priority job next
GraphNodes connected by arbitrary edges.Road network for a GPS route planner
SetUnique values, usually a map[T]struct.Tracking unique visitor IDs for a day
TrieTree indexed by prefix, one branch per character.Spell checker or search-bar suggestions
RingCircular list, last node points back to first.Round-robin load balancing across servers

An array has a fixed length that's part of its type — [5]int and [10]int are different types. Rarely used directly; slices wrap arrays and are far more common.

var a [5]int // fixed size, part of the type

A slice is a small header (pointer, length, capacity) pointing at a backing array. Appending past capacity allocates a new, larger array and copies the data over.

Slice header pointing into a backing array with unused capacity slice header ptr len = 3 cap = 5 10 20 30 unused unused backing array (len 3, cap 5 — 2 slots free before reallocation)

A struct groups named fields into one type. It's Go's building block for records — no classes, no inheritance, just composition.

type Config struct {
    Host string
    Port int
}

A map is a hash table: unordered key-value pairs with O(1) average lookup. Iteration order is intentionally randomized by the runtime.

m := map[string]int{
    "a": 1,
    "b": 2,
}

A singly linked list chains nodes with one pointer each. Cheap to insert at the head, but O(n) to reach an arbitrary node — no random access like a slice.

type Node struct {
    Value int
    Next  *Node
}

A stack (LIFO) and queue (FIFO) are usage patterns, not distinct Go types — both are typically built from a slice or linked list, differing only in which end you push and pop from.

Stack popping from the top versus queue dequeuing from the frontstack (LIFO) 30 20 10 pop (top) queue (FIFO) 10 20 30 dequeue (front) undo history: last action popped first print queue: first job printed first

A binary tree links each node to at most two children. Search trees keep values ordered so lookup, insert, and delete run in O(log n) when balanced.

type TreeNode struct {
    Value       int
    Left, Right *TreeNode
}

A heap keeps the smallest (or largest) element accessible in O(1), with O(log n) insert and removal. Go's container/heap turns any type implementing its interface into a heap.

h := &IntHeap{5, 2, 8}
heap.Init(h)
heap.Push(h, 1) // container/heap

A graph models nodes and arbitrary connections between them, commonly as an adjacency list — a map from node to its neighbors. Go has no built-in graph type.

type Graph struct {
    Edges map[string][]string
}