DEV Community

Cover image for Go: Learning Journey Through Algorithms
Asher Buk
Asher Buk

Posted on • Edited on

Go: Learning Journey Through Algorithms

I've been working with Node.js and its ecosystem. Now I’m diving deep into Go and I'm getting huge enjoyment from its approach — on one hand, simplicity and no syntactic sugar (you can get diabetes from all the sugar in JS, it's too sweet🙃), on the other hand, incredible capabilities and a greater sense of being "close to hardware."

I decided to document my learning notes in an open repo AlgoDSgo — specifically, implementations of classic algorithms in Go. This isn't production code, but educational examples with comments and Big O complexity analysis.

Sure, there are hundreds of similar repos... so what's the value in opening another one? 👇

  • Classic solutions to classic CS problems, without over-engineering or language-specific optimizations, for clear understanding of the algorithm.

  • Meaningful semantic naming

  • Aiming for simple and idiomatic Go code

  • Breakdowns and diagrams right in the comments

What's included:

algorithms/
├── search/
│   ├── Binary
│   ├── Linear
│   ├── Jump
│   ├── BFS Filesystem · BFS Graph Queue
│   └── DFS Filesystem · DFS Graph Recursive · DFS Graph Stack
└── sort/
    ├── Bubble
    ├── Selection
    ├── Insertion
    ├── Merge
    ├── Quick
    ├── Quick In-Place
    └── Heap

datastructures/
└── Planned

leetcode/
├── Two Sum #1
├── Merge Sorted Array #88
└── Valid Palindrome #125

interview_exercises/
├── Reverse
├── Duplicates
├── Whitespaces
└── Longest

informatica/
├── Factorial
├── Fibonacci
├── Prime
└── Table

Breakdown example

// Breadth-First Search (BFS) - Graph Search
// Time: O(V + E) - where V is number of vertices and E is number of edges
// Space: O(V) - for visited map and queue (in worst case, all nodes in queue)

package main

import "fmt"

func FindNodeBFS(graph map[int][]int, start int, target int) (int, bool) {
    // Initialize visited map and queue with starting node
    visited := make(map[int]bool)
    queue := []int{start} // ← QUEUE (FIFO)
    visited[start] = true

    for len(queue) > 0 {
        node := queue[0]  // get first node
        queue = queue[1:] // and dequeue from the queue

        if node == target {
            return node, true // we found the target
        }
        // Explore all neighbors
        neighbors := graph[node]
        for _, neighbor := range neighbors {
            if !visited[neighbor] {
                visited[neighbor] = true
                queue = append(queue, neighbor) // enqueue unvisited neighbor
            }
        }
    }
    return 0, false
}

func main() {
    // Example graph as adjacency list
    graph := map[int][]int{
        1: {2, 3},
        2: {1, 4, 5},
        3: {1, 6},
        4: {2},
        5: {2, 6},
        6: {3, 5},
    }

    node, found := FindNodeBFS(graph, 1, 6)
    if found {
        fmt.Printf("Node %d found\n", node)
    } else {
        fmt.Println("Node not found")
    }
}

/*
How BFS graph search works:

Explores graph level by level using a queue (FIFO - First In, First Out).
Visits all neighbors at current distance before moving to next level.
Uses visited map to prevent cycles and repeated visits.

Parameters:
  - graph: adjacency list representation as map[int][]int
  - start: starting node to begin search
  - target: node value to search for

Returns:
  - int: the found node value, or 0 if not found
  - bool: true if node was found, false otherwise

Graph representation - Adjacency List:

map[int][]int is a map where:
  - key (int): node identifier
  - value ([]int): slice of neighbor nodes that this node connects to

Example graph from main():

    graph := map[int][]int{
        1: {2, 3},
        2: {1, 4, 5},
        3: {1, 6},
        4: {2},
        5: {2, 6},
        6: {3, 5},
    }

Visual representation:

         1
        / \
       2   3
      /|   |\
     4 5   6 |
        \ /  |
         *---*

Adjacency list breakdown:

    Node 1 → neighbors [2, 3]       (1 connects to 2 and 3)
    Node 2 → neighbors [1, 4, 5]    (2 connects to 1, 4, and 5)
    Node 3 → neighbors [1, 6]       (3 connects to 1 and 6)
    Node 4 → neighbors [2]          (4 connects to 2)
    Node 5 → neighbors [2, 6]       (5 connects to 2 and 6)
    Node 6 → neighbors [3, 5]       (6 connects to 3 and 5)

BFS Traversal example (start=1, target=6):

Step 1: queue=[1], visited={1}
        Process node 1 → add neighbors 2,3

Step 2: queue=[2,3], visited={1,2,3}
        Process node 2 → add neighbors 4,5 (1 already visited)

Step 3: queue=[3,4,5], visited={1,2,3,4,5}
        Process node 3 → add neighbor 6 (1 already visited)

Step 4: queue=[4,5,6], visited={1,2,3,4,5,6}
        Process node 4 → no new neighbors

Step 5: queue=[5,6], visited={1,2,3,4,5,6}
        Process node 5 → no new neighbors (2,6 already visited)

Step 6: queue=[6], visited={1,2,3,4,5,6}
        Process node 6 → target found! ✓

Key differences from file system BFS:
  - Works on general graphs (can have cycles)
  - Requires visited map to prevent infinite loops
  - Graph nodes can have multiple incoming edges (multiple "parents")
  - map[int][]int structure instead of os.ReadDir()
*/
Enter fullscreen mode Exit fullscreen mode

I'm planning to expand it by adding data structures and more LeetCode problems.
If you're also learning Go or algorithms — I'd be happy if this helps you and to hear your feedback!

Repository: github.com/AshBuk/AlgoDSgo

Top comments (4)

Collapse
 
rouqe profile image
Jimben Honeyfield • Edited

Interesting! I've been learning Go recently, and I think this could be just the thing for me to get more familiar with DSA in Go! Thanks for this!

Collapse
 
ashbuk profile image
Asher Buk • Edited

Thanks! I hope it really helps! I tried to keep things readable also for people coming from other languages. Though there are Go-specific approaches in there as well, in addition to the classic ones.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.