Goroutines and Channels in Go Explained

A
Author
15 Sep, 2026 1 min read 611 views

A goroutine is a lightweight thread managed by the Go runtime. You can run hundreds of thousands of them. Channels let goroutines pass data safely.

Start goroutines and wait for them

var wg sync.WaitGroup
urls := []string{"https://go.dev", "https://pkg.go.dev", "https://example.com"}

for _, url := range urls {
    wg.Go(func() {             // Go 1.25+; earlier: wg.Add(1) + defer wg.Done()
        resp, err := http.Get(url)
        if err != nil {
            log.Println(url, err)
            return
        }
        resp.Body.Close()
        log.Println(url, resp.Status)
    })
}
wg.Wait()

Since Go 1.22 each loop iteration has its own url variable, so capturing it in a goroutine is safe.

Channels

results := make(chan string)

go func() {
    results <- "done"     // send (blocks until someone receives)
}()

msg := <-results          // receive

A worker pool

jobs := make(chan int, 100)
results := make(chan int, 100)

for w := 1; w <= 4; w++ {
    go func() {
        for n := range jobs {   // loops until jobs is closed
            results <- n * n
        }
    }()
}

for i := 1; i <= 20; i++ {
    jobs <- i
}
close(jobs)

for i := 0; i < 20; i++ {
    fmt.Println(<-results)
}

select: wait on several channels

select {
case res := <-results:
    fmt.Println("got", res)
case <-time.After(2 * time.Second):
    fmt.Println("timed out")
case <-ctx.Done():
    return ctx.Err()
}

Avoid these mistakes

  • Goroutine leaks: a goroutine blocked forever on a channel nobody reads. Always give goroutines a way to stop (a closed channel or a cancelled context).
  • Data races: two goroutines writing the same variable. Run tests with go test -race.
  • Only the sender should close a channel, and only once.
  • For simple shared counters or maps, a sync.Mutex is often clearer than channels.
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.