Concurrency with Goroutines
Go’s concurrency model, built on goroutines and channels, allows for efficient handling of multiple tasks simultaneously. This enhances performance and responsiveness, especially in scenarios requiring I/O operations or complex computations.
What are Goroutines?
Goroutines are lightweight, concurrent execution units managed by the Go runtime. They are created using the go
keyword, which launches a new goroutine to execute a function concurrently. [Source: https://go.dev/blog/concurrency-is-not-parallelism]
Example:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
Why is Concurrency with Goroutines Important?
Concurrency empowers Go programs to:
- Improve Responsiveness: Allowing tasks to run in parallel prevents blocking of the main thread, ensuring responsiveness to user interactions.
- Maximize CPU Utilization: Goroutines effectively leverage multi-core processors, enabling parallel execution of tasks for enhanced performance.
- Simplified Code Structure: Go’s concurrency features allow for clean and modular code, making it easier to manage complex systems.
Channels
Channels act as communication pathways between goroutines. They provide a safe and synchronized method for passing data between concurrently running functions.
Example:
package main
import (
"fmt"
)
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // Send sum to channel c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int) // Create a channel
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x := <-c // Receive from c
y := <-c // Receive from c
fmt.Println(x, y, x+y)
}
This example demonstrates how channels facilitate communication and synchronization between goroutines, allowing for efficient data processing.