Concurrency lets your program do many things at the same time. Common patterns help you organize this work safely and clearly.
Common concurrency patterns in Go
package main import ( "fmt" "sync" ) func main() { // Example of a concurrency pattern }
Go uses goroutines to run functions concurrently.
Channels help goroutines communicate safely.
go func() {
fmt.Println("Hello from a goroutine")
}()ch := make(chan int) go func() { ch <- 42 // send value to channel }() val := <-ch // receive value from channel fmt.Println(val)
var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() fmt.Println("Work done") }() wg.Wait()
jobs := make(chan int, 3) results := make(chan int, 3) // Worker function worker := func(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Printf("worker %d started job %d\n", id, j) results <- j * 2 } } func main() { for w := 1; w <= 3; w++ { go worker(w, jobs, results) } for j := 1; j <= 5; j++ { jobs <- j } close(jobs) for a := 1; a <= 5; a++ { fmt.Println("result:", <-results) } }
This program uses a worker pool pattern. It starts 3 workers that get jobs from a channel. Each worker does some work (simulated by sleep) and sends results back. The main function waits for all workers to finish and then prints the results.
package main import ( "fmt" "sync" "time" ) func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) { defer wg.Done() for j := range jobs { fmt.Printf("Worker %d started job %d\n", id, j) time.Sleep(time.Second) // simulate work fmt.Printf("Worker %d finished job %d\n", id, j) results <- j * 2 } } func main() { jobs := make(chan int, 5) results := make(chan int, 5) var wg sync.WaitGroup // Start 3 workers for w := 1; w <= 3; w++ { wg.Add(1) go worker(w, jobs, results, &wg) } // Send 5 jobs for j := 1; j <= 5; j++ { jobs <- j } close(jobs) // Wait for all workers to finish wg.Wait() close(results) // Collect results for res := range results { fmt.Println("Result:", res) } }
Always close channels when no more values will be sent to avoid deadlocks.
Use WaitGroup to wait for goroutines to finish before exiting main.
Be careful to avoid race conditions when sharing data between goroutines.
Concurrency lets your program do many things at once using goroutines.
Channels help goroutines talk to each other safely.
Common patterns like worker pools and WaitGroups help organize concurrent work clearly.