๐Ÿ‘ˆ Back

Data Structures in Go: A Comprehensive Guide

Exploring arrays, slices, maps, structs, and more in Go

By Keith Thomson โ€ข 15 min read โ€ข golang

๐Ÿน Go provides a rich set of built-in data structures that make it powerful for both systems programming and application development.

In this guide, weโ€™ll explore the core data structures available in Go, explain how they work, and show practical code examples.

๐Ÿ”ข Arrays

An array in Go is a fixed-size, ordered collection of elements.

package main

import "fmt"

func main() {
    var arr [3]int = [3]int{1, 2, 3}
    fmt.Println(arr)

    // Iterate
    for i, v := range arr {
        fmt.Printf("Index %d = %d
", i, v)
    }
}
  • Arrays have a fixed length.
  • Useful when the size is known and constant.

๐Ÿ“ Slices

A slice is a dynamically-sized, flexible view into an array. Slices are the most commonly used data structure in Go.

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5}
    slice = append(slice, 6)
    fmt.Println(slice)
    fmt.Println("Length:", len(slice), "Capacity:", cap(slice))
}
  • Built on top of arrays.
  • Support dynamic resizing with append.
  • Preferred over arrays in most cases.

๐Ÿ—บ Maps

A map is Goโ€™s built-in hash table implementation for key-value pairs.

package main

import "fmt"

func main() {
    m := map[string]int{
        "Alice": 25,
        "Bob":   30,
    }
    m["Charlie"] = 35

    for k, v := range m {
        fmt.Printf("%s is %d years old
", k, v)
    }
}
  • Keys must be comparable (e.g., strings, ints).
  • Lookups are O(1) on average.

๐Ÿ— Structs

A struct groups fields together, making it Goโ€™s way of creating custom data types.

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p.Name, "is", p.Age)
}
  • Structs are used for modeling entities.
  • They are the building blocks of more complex data structures.

๐Ÿ”— Linked Lists

Goโ€™s standard library provides a doubly linked list via container/list.

package main

import (
    "container/list"
    "fmt"
)

func main() {
    l := list.New()
    l.PushBack(1)
    l.PushBack(2)
    l.PushFront(0)

    for e := l.Front(); e != nil; e = e.Next() {
        fmt.Println(e.Value)
    }
}
  • Each element points to the next and previous nodes.
  • Efficient for insertions/removals in the middle.

๐Ÿ“š Stacks

A stack is a LIFO (Last In, First Out) structure. Implemented easily with slices.

package main

import "fmt"

type Stack []int

func (s *Stack) Push(v int) {
    *s = append(*s, v)
}

func (s *Stack) Pop() int {
    if len(*s) == 0 {
        panic("stack is empty")
    }
    val := (*s)[len(*s)-1]
    *s = (*s)[:len(*s)-1]
    return val
}

func main() {
    var s Stack
    s.Push(10)
    s.Push(20)
    fmt.Println(s.Pop()) // 20
}
  • Built using slices.
  • Great for recursion-like problems, parsing, and backtracking.

๐Ÿ“ฌ Queues

A queue is a FIFO (First In, First Out) structure. Also implemented with slices.

package main

import "fmt"

type Queue []int

func (q *Queue) Enqueue(v int) {
    *q = append(*q, v)
}

func (q *Queue) Dequeue() int {
    if len(*q) == 0 {
        panic("queue is empty")
    }
    val := (*q)[0]
    *q = (*q)[1:]
    return val
}

func main() {
    var q Queue
    q.Enqueue(1)
    q.Enqueue(2)
    fmt.Println(q.Dequeue()) // 1
}
  • Useful for scheduling and breadth-first search (BFS).

โ›ฐ Heaps & Priority Queues

Go provides heap operations in the container/heap package.

package main

import (
    "container/heap"
    "fmt"
)

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 any) {
    *h = append(*h, x.(int))
}

func (h *IntHeap) Pop() any {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[0 : n-1]
    return x
}

func main() {
    h := &IntHeap{3, 1, 4}
    heap.Init(h)
    heap.Push(h, 2)
    fmt.Println(heap.Pop(h)) // 1 (smallest element)
}
  • Implements a min-heap by default.
  • Can be adapted into a priority queue.

๐Ÿ Conclusion

Go provides both high-level abstractions (slices, maps, structs) and low-level control (linked lists, heaps).
By mastering these data structures, youโ€™ll be ready to build efficient algorithms, design scalable applications, and handle both systems and business logic effectively.

๐Ÿ’ก Next Step: Try implementing algorithms like BFS, DFS, and Dijkstraโ€™s algorithm using these data structures to strengthen your understanding.