Courses/Go/Concurrency with Goroutines

    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
    • select for 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

    Try it Yourself »
    JavaScript
    // 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

    Try it Yourself »
    JavaScript
    // 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

    Try it Yourself »
    JavaScript
    // 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

    Try it Yourself »
    JavaScript
    // 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

    ⚠️
    Goroutine leaks — Always ensure goroutines can exit. Use done channels or context cancellation.
    ⚠️
    Race conditions — Use go run -race to detect data races. Never access shared variables without synchronization.
    💡
    Pro Tip: Prefer channels over mutexes. Channels make data flow explicit and are easier to reason about.

    📋 Quick Reference

    PatternGo Syntax
    Goroutinego myFunc()
    Channelch := make(chan int)
    Sendch <- value
    Receiveval := <-ch
    Selectselect { case v := <-ch: ... }
    WaitGroupwg.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.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service