Algorithms and Data Structures in Go: From Basics to Practice
Go (Golang) is a compiled language with strong typing, created at Google for solving high-performance and scalability problems. Unlike Python, which is often used for prototyping, Go requires a deep understanding of memory management and algorithmic efficiency from the developer. In this article, we will break down key data structures and algorithms in Go with practical code examples.
Why is it important to study algorithms and data structures in Go?
Go is actively used in backend development, microservices, DevOps tools (Docker, Kubernetes), and high-load systems. Without understanding data structures, you will not be able to:
- Optimize the execution time of database queries
- Write efficient HTTP request handlers
- Work with large volumes of data in real time
- Pass technical interviews at top IT companies
Go provides built-in structures: array, slice, map, but for complex tasks (e.g., graphs or trees) they have to be implemented manually. Let's break down each structure.
1. Basic Data Structures in Go
Arrays and Slices
An array in Go is a fixed sequence of elements of the same type. A slice is a dynamic wrapper over an array that allows you to change its size.
package main
import "fmt"
func main() { // Fixed-length array var arr [5]int = [5]int{1, 2, 3, 4, 5} fmt.Println("Array:", arr)
// Slice (dynamic array) slice := []int{10, 20, 30} slice = append(slice, 40, 50) fmt.Println("Slice:", slice)
// Slice of a slice subSlice := slice[1:4] fmt.Println("Sub-slice:", subSlice)}When to use: Arrays — for fixed data (e.g., point coordinates). Slices — for any dynamic collections. Slices in Go are analogous to lists in Python, but with more efficient memory management.
Hash Tables (Map)
Map is a built-in hash table that provides data access in O(1) on average.
package main
import "fmt"
func main() { // Creating a map scores := make(map[string]int) scores["Alice"] = 95 scores["Bob"] = 87
// Reading with check if val, ok := scores["Alice"]; ok { fmt.Println("Alice:", val) }
// Deletion delete(scores, "Bob")
// Iteration for name, score := range scores { fmt.Printf("%s: %d", name, score) }}Tip: In Go, map does not guarantee element order. If you need an ordered dictionary — use a slice of key-value pairs with sorting.
2. Implementing Complex Data Structures
Stack and Queue
Go does not have built-in stack or queue, but they are easy to implement using slices.
package main
import "fmt"
// Stack (LIFO)type Stack []int
func (s *Stack) Push(v int) { *s = append(*s, v)}
func (s *Stack) Pop() (int, bool) { if len(*s) == 0 { return 0, false } v := (*s)[len(*s)-1] *s = (*s)[:len(*s)-1] return v, true}
// Queue (FIFO)type Queue []int
func (q *Queue) Enqueue(v int) { *q = append(*q, v)}
func (q *Queue) Dequeue() (int, bool) { if len(*q) == 0 { return 0, false } v := (*q)[0] *q = (*q)[1:] return v, true}
func main() { stack := Stack{} stack.Push(1) stack.Push(2) fmt.Println("Pop:", stack.Pop()) // 2
queue := Queue{} queue.Enqueue(10) queue.Enqueue(20) fmt.Println("Dequeue:", queue.Dequeue()) // 10}Performance: Insertion and deletion from the beginning of a slice (queue) — O(n