Concurrency Basics

Overview

Go’s concurrency model uses goroutines (lightweight threads) and channels for communication.

Goroutines

go func() {
    // Runs concurrently
    fmt.Println("Hello from goroutine")
}()

go processData()  // Named function

Goroutines are cheap (~2KB stack, can have millions).

Creating Goroutines

func main() {
    go sayHello()
    go sayWorld()
    time.Sleep(100 * time.Millisecond)  // Wait (not ideal)
}

func sayHello() { fmt.Println("Hello") }
func sayWorld() { fmt.Println("World") }

Waiting with WaitGroup

var wg sync.WaitGroup

for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(n int) {
        defer wg.Done()
        fmt.Println(n)
    }(i)
}

wg.Wait()  // Block until all done

Channels

ch := make(chan int)      // Unbuffered
ch := make(chan int, 10)  // Buffered

ch <- 42      // Send
value := <-ch // Receive

Basic Channel Pattern

func main() {
    ch := make(chan string)

    go func() {
        ch <- "Hello"
    }()

    msg := <-ch
    fmt.Println(msg)
}

Worker Pool

func worker(id int, jobs <-chan int, results chan<- int) {
    for job := range jobs {
        results <- job * 2
    }
}

func main() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)

    // Start workers
    for w := 0; w < 3; w++ {
        go worker(w, jobs, results)
    }

    // Send jobs
    for j := 0; j < 10; j++ {
        jobs <- j
    }
    close(jobs)

    // Collect results
    for r := 0; r < 10; r++ {
        fmt.Println(<-results)
    }
}

Summary

Concept Purpose
go func() Start goroutine
sync.WaitGroup Wait for completion
make(chan T) Create channel
ch <- / <-ch Send/receive