Concurrency
Goroutines and Channels
Harness Go's built-in concurrency with goroutines and channels.
Goroutines
A goroutine is a lightweight thread managed by the Go runtime. You can run thousands of goroutines concurrently.
Start a goroutine with the go keyword before a function call.
Channels
Channels are the pipes that connect goroutines. Send and receive values between goroutines.
ch <- value— sendvalue := <-ch— receive
WaitGroups
Use sync.WaitGroup to wait for a group of goroutines to finish.
Select
select is like a switch for channel operations. It blocks until one case is ready.
Example
go
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // decrement counter when done
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
// Pipeline pattern with channels
func generate(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func square(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
func main() {
// Basic goroutine with WaitGroup
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, &wg)
}
wg.Wait()
fmt.Println("All workers done")
// Channel pipeline
nums := generate(2, 3, 4, 5)
squares := square(nums)
for n := range squares {
fmt.Print(n, " ") // 4 9 16 25
}
fmt.Println()
// Select with timeout
ch := make(chan string)
go func() {
time.Sleep(2 * time.Second)
ch <- "result"
}()
select {
case res := <-ch:
fmt.Println("Got:", res)
case <-time.After(1 * time.Second):
fmt.Println("Timeout!")
}
}Try it yourself — GO