Stop Watching Go Tutorials. Start Doing the Reps.

go dev.to

I Built an Open-Source Desktop App to Learn Go the Right Way — Here's Why It Works

250+ test-driven exercises, a real Go toolchain, and a skill tree that stops you from skipping the fundamentals.


The problem with how most of us "learn Go"

You know the cycle. You read A Tour of Go, nod along, watch a YouTube playlist, then jump straight into a side project. Two weeks in, you're Googling "golang waitgroup vs channel" for the fourth time and copy‑pasting a select block you don't fully understand.

The issue isn't Go. Go is small on purpose. The issue is that reading is not learning, and tutorials don't fail loudly when you skip a concept. You think you "get" channels until you have to build a worker pool from scratch — and suddenly your goroutines deadlock.

After hitting that wall myself, I built the tool I wished existed. It's open source, it runs locally, and it's called Go Dojo.

Repo: github.com/Lutif/go-dojo — stars and forks help more people find it.


What is Go Dojo?

Go Dojo is a cross‑platform desktop app (Electron + React + TypeScript) that turns your laptop into an interactive Go training ground. You write Go in a Monaco editor (the same one VS Code uses), hit Cmd+Enter, and the app spawns a real go test process in a sandboxed temp directory and streams the results back to you.

No browser sandbox. No fake "Go playground." Your actual Go toolchain, your actual test runner, with a curriculum on top.

What's in the box

  • 250+ exercises across 10 categories: Basics, Type System, Error Handling, Concurrency, Standard Library, Patterns, Internals, Networking, Data & Storage, and multi‑step Projects.
  • A dependency-aware skill tree — exercises stay locked until you've completed their prerequisites. No skipping channels and pretending select will be fine.
  • Test-driven by default — every exercise ships with a Go test file. Green tests are the only definition of "done."
  • Multi-step capstone projects — build a CLI, a Lexer, and a full Monkey programming language interpreter step by step.
  • Auto-saved drafts, bookmarks, and progress persisted to ~/.go-dojo-progress.json.
  • Dark theme, keyboard shortcuts, hints, reference solutions — all the table stakes done right.

What an exercise actually looks like

Every exercise is a single TypeScript object. Here's the very first one — basics_01_hello, as it lives in the repo today:

const exercise: Exercise = {
  id: 'basics_01_hello',
  title: 'Hello World',
  category: 'Basics',
  difficulty: 'beginner',
  description: `This is your first program in Go. Each source file lives in
  a **package**; programs you run with \`go run\` use \`package main\`...`,
  code: `package main

import "fmt"

// TODO: Call fmt.Println to output "Hello, World!"
func main() {

}`,
  testCode: `package main

import (
  "bytes"; "io"; "os"; "testing"
)

func TestMain(t *testing.T) {
  r, w, _ := os.Pipe()
  stdout := os.Stdout
  os.Stdout = w
  main()
  w.Close()
  os.Stdout = stdout

  var buf bytes.Buffer
  io.Copy(&buf, r)
  if buf.String() != "Hello, World!\n" {
    t.Errorf("got %q, want %q", buf.String(), "Hello, World!\n")
  }
}`,
  hints: [
    'Use fmt.Println("Hello, World!") — Println adds a newline automatically.',
    'In Go, unused imports cause a compile error.',
    'The string must match exactly: capital H, comma, exclamation mark.'
  ],
}
Enter fullscreen mode Exit fullscreen mode

Notice what's happening here: even on exercise #1, you're being introduced to stdout capture in tests — a real-world Go testing pattern. The curriculum isn't dumbed down; it just sequences the difficulty.


Now jump 18 exercises later: the Worker Pool

By the time you reach the concurrency track, you've already done goroutines, sync.WaitGroup, channels, buffered channels, channel direction, range over channels, select, mutexes, atomics, and context. Then this lands in your editor:

type Job struct {
    ID    int
    Input int
}

type Result struct {
    JobID  int
    Output int
}

// WorkerPool processes jobs with a fixed number of workers.
// Each worker takes a Job and produces a Result where Output = Input * Input.
func WorkerPool(numWorkers int, jobs []Job) []Result {
    // TODO
    return nil
}

// MapPool applies fn to each item using numWorkers goroutines.
// Returns results in the same order as input.
func MapPool(numWorkers int, items []int, fn func(int) int) []int {
    // TODO
    return nil
}
Enter fullscreen mode Exit fullscreen mode

The tests will hammer you with edge cases — empty inputs, single workers, and order preservation for MapPool. That second requirement is the trap. You can't just slap a channel on it; you need an indexed job struct so workers can write into the right slot. The hint nudges you there:

"MapPool: use an indexed job struct {index, value} so workers write to results[index]. This preserves input order without sorting."

This is the kind of subtlety you only internalize by writing it, breaking it, and watching go test go red.


Why test-driven exercises beat tutorials

Tutorials let you nod and move on. Tests don't.

  • Failure is unambiguous. --- FAIL: TestMapPoolPreservesOrder is not the same vibe as "wait, did I get that right?"
  • You're forced to read the spec. The test file is the requirements doc.
  • You learn idiomatic Go for free. Every exercise's test code uses standard testing patterns — table tests, subtests, t.Errorf vs t.Fatalf. By exercise 50 you're writing them yourself without thinking.
  • You build muscle memory. Channels, defer, error wrapping, context cancellation — the only way these stop feeling foreign is through repetition with feedback.

That's the dojo metaphor. You don't watch a black belt land 100 kicks. You land them yourself.


The skill tree: why you can't cheat the curriculum

A 47KB file called dependencies.ts maps every exercise to its prerequisites. Want to attempt conc_18_worker_pool? You need goroutines, WaitGroups, buffered channels, and range over channels first — all unlocked.

This is rendered as an interactive graph (powered by @xyflow/react + dagre) so you can visually see the path from "Hello World" to "Build a Monkey Interpreter."

Most learning platforms either give you a linear slog or a chaotic pile of exercises. Go Dojo gives you a DAG of competence — multiple valid paths through the language, but no way to fool yourself into attempting concurrency before you understand functions.


The capstone: build a real programming language

The crown jewel is the Monkey interpreter project — 22 sequenced steps that walk you through building a working interpreter for the Monkey language (popularized by Thorsten Ball's Writing an Interpreter in Go). You'll build:

  • A lexer (tokenizer with peek and read logic)
  • A Pratt parser with operator precedence
  • An AST evaluator with environments and closures
  • First-class functions, higher-order functions, error handling, built-ins

Plus other multi-step projects: a REST API, a production-grade CLI, and standalone lexer and parser tracks. By the end, you don't just know Go — you've shipped non-trivial Go.


Architecture (for the curious)

For developers who like to peek under the hood, the design is intentionally simple:

┌──────────────────────────┐         IPC           ┌─────────────────────────┐
│  Renderer (React + TS)   │  ◄─────────────────►  │  Main Process (Node)     │
│  • Monaco editor         │                       │  • Writes Go to /tmp     │
│  • Skill tree (xyflow)   │                       │  • Spawns `go test`      │
│  • Progress dashboard    │                       │  • Parses + cleans up    │
└──────────────────────────┘                       └─────────────────────────┘
Enter fullscreen mode Exit fullscreen mode
  • Main process (src/main/index.ts) writes your code + the test file to /tmp/go-dojo-{timestamp}/, runs go test -v -count=1 -timeout 10s ./..., parses the output, and cleans up.
  • Preload bridge exposes a typed window.api to the renderer — no nodeIntegration footguns.
  • Renderer is a normal React/TS app. Adding an exercise is literally one TypeScript file plus a one-line entry in dependencies.ts.

The whole thing is hackable in an afternoon. Which is the point.


Why this is valuable for you specifically

  • You're a backend dev curious about Go. Stop watching tutorials. Spend a weekend in the dojo and walk out writing idiomatic Go.
  • You're prepping for Go interviews. The concurrency, internals, and patterns categories are basically a curated interview prep curriculum.
  • You teach Go. Use Go Dojo with your team or class. Fork it, swap in your own exercises, ship internally.
  • You're a Go educator or content creator. The exercise format is dead simple to extend, and contributions are welcome.
  • You like learning by building. The Monkey interpreter alone is worth the install.

Get started in 60 seconds

You'll need Node.js 16+ and Go 1.21+ on your machine.

git clone https://github.com/Lutif/go-dojo.git
cd go-dojo
npm install
npm run dev
Enter fullscreen mode Exit fullscreen mode

Or grab a prebuilt binary from the Releases page — there are already 14 releases shipped.

Keyboard shortcuts to remember:

  • Cmd/Ctrl + Enter — run tests
  • Cmd/Ctrl + R — reset to starter code
  • Cmd/Ctrl + S — save (also auto-saved)

How you can help

Go Dojo is MIT licensed and built in the open. If it helps you, the single highest‑leverage thing you can do is:

Star the repo: github.com/Lutif/go-dojo

Stars are how other developers discover it on GitHub Trending and search. They're free for you and they directly compound the project's reach.

Beyond that:

  • Fork it and try adding an exercise — the format is one TypeScript file.
  • Open an issue if you spot a confusing exercise, a missing concept, or a bug.
  • Tackle a planned projectproj-kv, proj-log, proj-watcher, proj-git, and proj-container are scoped and waiting for a contributor.
  • Share this post with one friend who's been "meaning to learn Go." That's how communities are built.

Closing thought

The best programmers I know didn't learn their craft by reading. They learned by shipping small things, getting feedback, and shipping again. Go Dojo is just a structured way to do that 250 times in a row, with a real compiler grading your work.

If that sounds like the kind of practice you've been missing — give it a try, leave a star, and let me know what you build.

github.com/Lutif/go-dojo


If this post helped, give it a clap (or 50 — Medium lets you), and follow for more deep dives on Go, developer tooling, and learning-in-public projects.


Source: dev.to

arrow_back Back to Tutorials