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 theok
idiom:value, ok := <-ch
. Ifok
isfalse
, the channel is closed, andvalue
will 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.