Lesson 5 • Intermediate
Concurrency with Goroutines 🐹
Unlock Go's superpower — run thousands of goroutines, communicate with channels, and master concurrency patterns like fan-out/fan-in.
What You'll Learn in This Lesson
- • Goroutines — lightweight concurrent execution
- • Channels for safe communication between goroutines
- •
selectfor multiplexing channels - • WaitGroup, Mutex, and synchronization
- • Fan-out/fan-in and pipeline patterns
1️⃣ Goroutines
A goroutine is a function running concurrently with other goroutines. Just add go before a function call. They're incredibly lightweight — you can run millions of them.
Try It: Goroutines
Launch concurrent goroutines and see the speedup
// Goroutines — Lightweight Concurrent Execution
console.log("=== What Are Goroutines? ===");
console.log("A goroutine is a lightweight thread managed by Go runtime.");
console.log("They cost ~2KB of stack vs ~1MB for OS threads.");
console.log("You can run MILLIONS of goroutines simultaneously!");
console.log();
console.log("=== Starting a Goroutine ===");
console.log(" func sayHello(name string) {");
console.log(' fmt.Println("Hello,", name)');
console.log(" }");
console.log();
console
...2️⃣ Channels
Channels are Go's primary way for goroutines to communicate. They're typed, thread-safe pipes. Sending and receiving block until the other side is ready, providing built-in synchronization.
Try It: Channels
Send and receive values between goroutines
// Channels — Communication Between Goroutines
console.log("=== Channels ===");
console.log('"Don\'t communicate by sharing memory;');
console.log(' share memory by communicating." — Go Proverb');
console.log();
console.log("=== Creating Channels ===");
console.log(" ch := make(chan string) // Unbuffered channel");
console.log(" ch := make(chan int, 10) // Buffered (capacity 10)");
console.log();
console.log("=== Sending & Receiving ===");
console.log(' ch <- "hello" // Send to ch
...3️⃣ Select & Synchronization
select lets you wait on multiple channel operations simultaneously — perfect for timeouts, cancellation, and multiplexing. sync.WaitGroup waits for all goroutines to finish.
Try It: Select & WaitGroup
Timeouts, cancellation, and waiting for goroutines
// Select — Multiplexing Channels
console.log("=== select Statement ===");
console.log("select lets you wait on multiple channel operations.");
console.log("It's like a switch statement for channels.");
console.log();
console.log(" select {");
console.log(" case msg := <-ch1:");
console.log(' fmt.Println("From ch1:", msg)');
console.log(" case msg := <-ch2:");
console.log(' fmt.Println("From ch2:", msg)');
console.log(" case ch3 <- value:");
console.log(' fmt.Println("Sent to
...4️⃣ Concurrency Patterns
Fan-out distributes work across multiple goroutines. Fan-in merges results. Pipelines chain processing stages. Mutexes protect shared state when channels aren't appropriate.
Try It: Patterns
Fan-out/fan-in, pipelines, and mutexes
// Concurrency Patterns
console.log("=== Fan-Out / Fan-In ===");
console.log("Fan-out: Multiple goroutines read from same channel");
console.log("Fan-in: Multiple channels merged into one");
console.log();
console.log(" // Fan-out: 3 workers reading from jobs channel");
console.log(" for i := 0; i < 3; i++ {");
console.log(" go worker(jobs, results)");
console.log(" }");
console.log();
// Simulate fan-out
console.log(" Job distribution:");
const workers = ["Worker-1", "Worker-2", "
...⚠️ Common Mistakes
go run -race to detect data races. Never access shared variables without synchronization.📋 Quick Reference
| Pattern | Go Syntax |
|---|---|
| Goroutine | go myFunc() |
| Channel | ch := make(chan int) |
| Send | ch <- value |
| Receive | val := <-ch |
| Select | select { case v := <-ch: ... } |
| WaitGroup | wg.Add(1); defer wg.Done() |
🎉 Lesson Complete!
You've mastered Go's concurrency model! Next, we'll learn Go's unique approach to error handling.
Sign up for free to track which lessons you've completed and get learning reminders.