</>
Skip to content
Go lessons (27/34)

Go — Goroutines

Basic goroutine

package main

import (
    "fmt"
    "time"
)

func worker(name string) {
    for i := 0; i < 5; i++ {
        fmt.Printf("%s: %d\n", name, i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    go worker("A") // Start goroutine
    go worker("B")

    time.Sleep(1 * time.Second) // Wait for goroutines
}

WaitGroup

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            fmt.Printf("Worker %d done\n", id)
        }(i)
    }

    wg.Wait()
    fmt.Println("All workers done")
}

Mutex

package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.Mutex
    counter := 0
    var wg sync.WaitGroup

    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mu.Lock()
            counter++
            mu.Unlock()
        }()
    }

    wg.Wait()
    fmt.Println("Counter:", counter)
}

Channel basics

ch := make(chan int)

// Sender
go func() {
    ch <- 42
}()

// Receiver
value := <-ch
fmt.Println(value)

Buffered channels

ch := make(chan int, 5) // Buffer size 5

ch <- 1
ch <- 2
ch <- 3

fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2

Select

ch1 := make(chan string)
ch2 := make(chan string)

go func() {
    time.Sleep(1 * time.Second)
    ch1 <- "one"
}()

go func() {
    time.Sleep(2 * time.Second)
    ch2 <- "two"
}()

for i := 0; i < 2; i++ {
    select {
    case msg := <-ch1:
        fmt.Println("Received:", msg)
    case msg := <-ch2:
        fmt.Println("Received:", msg)
    }
}

Best practices

  • Use WaitGroup for waiting on goroutines
  • Use Mutex for shared state
  • Prefer channels over mutexes for communication
  • Use select for multiple channel operations
  • Always handle errors in goroutines

Mini Practice

Write Go code that:

  1. Launches 5 goroutines with a WaitGroup
  2. Uses a mutex to protect shared state
  3. Sends and receives on a buffered channel
  4. Uses select with multiple channels

Up Next

In the next lesson, you'll learn about Channels — Go's concurrency primitive.

Related Topics

Frequently Asked Questions about Goroutines

What is Goroutines in Go?

Goroutines is a fundamental concept in Go. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Goroutines?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Goroutines.

Why is Goroutines important in Go?

Goroutines is essential for Go development. Understanding this concept will help you write better code and solve real-world problems more effectively.