Go > Concurrency > Goroutines > Creating goroutines
Goroutines with Channels
This example demonstrates how to use channels to communicate between goroutines and synchronize their execution.
Goroutines with Channels
This code creates a worker pool of goroutines that process jobs sent through a channel. The jobs channel sends integers representing the 'jobs' to be executed. The results channel collects the processed results. The `worker` function receives jobs from the jobs channel, simulates work with time.Sleep, and sends the result to the results channel. `close(jobs)` signal to the workers that no more jobs will be sent. Finally, the main function collects and prints the results from the `results` channel.
package main
import (
"fmt"
"time"
)
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("worker:%d started job:%d\n", id, j)
time.Sleep(time.Second)
fmt.Printf("worker:%d finished job:%d\n", id, j)
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
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(<-results)
}
close(results)
}
Understanding the Code
jobs channel.<-chan and chan<- syntax specifies the direction of the channel. <-chan int means the channel can only be received from, and chan<- int means the channel can only be sent to.
Concepts Behind the Snippet
Real-Life Use Case
This pattern is common in distributed systems, where workers are responsible for processing tasks assigned by a central coordinator. The coordinator sends tasks to the worker pool, and the workers send the results back to the coordinator. This allows for efficient parallel processing of tasks.
Best Practices
ok idiom (value, ok := <-ch).
Interview Tip
Be prepared to explain the different types of channels (buffered vs. unbuffered) and how they affect the behavior of goroutines. Also, be able to describe how channels are used for synchronization and communication.
When to Use Them
Use channels when you need to communicate between goroutines in a safe and synchronized manner. They are particularly useful for implementing worker pools, message queues, and other concurrent patterns.
Memory Footprint
The memory footprint of channels depends on the size of the data being sent and the capacity of the channel (for buffered channels). However, channels are generally lightweight and efficient.
Alternatives
Alternatives to channels include using mutexes and condition variables, but channels are generally preferred for communication between goroutines due to their simplicity and safety.
Pros
Cons
FAQ
-
What is the difference between buffered and unbuffered channels?
Unbuffered channels require both the sender and receiver to be ready at the same time. Buffered channels, on the other hand, can store a certain number of values, allowing the sender to send data even if the receiver is not immediately ready, up to the channel's capacity. -
How do I detect when a channel is closed?
You can use theokidiom:value, ok := <-ch. Ifokisfalse, the channel is closed, andvaluewill be the zero value of the channel's type. -
Can I send nil values on a channel?
Yes, you can send nil values on a channel. This can be useful for signaling purposes.