Practical Concurrency Use Cases
Concurrency in Go can be applied to a wide range of practical use cases, from parallel processing to network programming. Here are some examples of how concurrency can be used in real-world applications:
Parallel Processing
One of the most common use cases for concurrency in Go is parallel processing. This can be useful for tasks that can be divided into independent subtasks, such as data processing, image processing, or scientific computing.
func main() {
// Create a slice of numbers to process
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// Create a channel to receive the processed results
results := make(chan int, len(numbers))
// Start the worker goroutines
for _, num := range numbers {
go func(n int) {
// Process the number
result := n * n
results <- result
}(num)
}
// Collect the results
for i := 0; i < len(numbers); i++ {
fmt.Println(<-results)
}
}
Responsive Design
Concurrency can also be used to build responsive and scalable web applications. By using goroutines and channels, you can handle multiple client requests concurrently, improving the overall responsiveness and throughput of your application.
func main() {
// Create a channel to receive client requests
requests := make(chan *http.Request, 100)
// Start the worker goroutines
for i := 0; i < 10; i++ {
go func() {
for req := range requests {
// Process the request
handleRequest(req)
}
}()
}
// Start the HTTP server
http.ListenAndServe(":8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Add the request to the channel
requests <- r
}))
}
func handleRequest(r *http.Request) {
// Process the request
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
Network Programming
Concurrency is also essential for network programming in Go. By using goroutines and channels, you can handle multiple network connections concurrently, allowing your application to scale and handle high-load scenarios.
func main() {
// Create a TCP listener
listener, err := net.Listen("tcp", ":8080")
if err != nil {
// Handle the error
return
}
defer listener.Close()
// Accept incoming connections
for {
conn, err := listener.Accept()
if err != nil {
// Handle the error
continue
}
// Handle the connection in a new goroutine
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
// Read and process the data from the connection
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
// Handle the error
return
}
// Process the data
fmt.Println(string(buf[:n]))
}
}
These are just a few examples of how concurrency can be used in practical applications. By understanding the fundamentals of concurrency in Go and applying the appropriate patterns and best practices, developers can build efficient, scalable, and responsive applications that take full advantage of modern hardware and the power of the Go programming language.