What are the Channels in Golang
Channels are a powerful feature of Go that enable communication between goroutines. They are used to send and receive data between goroutines and synchronize their execution.
Channels are a fundamental part of Go's concurrency model and are used extensively in Go programs to coordinate the execution of concurrent tasks.
Create a new Channel#
To create a new channel, you can use the make function with the chan keyword followed by the type of data that the channel will carry. For example:
ch := make(chan int)
In the above example, we create a new channel ch that can carry integers.
Channels can also carry other types of data, such as strings, structs, or custom types.
Sending and receiving data#
You can send data to a channel using the <- operator followed by the channel variable. For example:
ch <- 42
In the above example, we send the integer 42 to the channel ch.
You can receive data from a channel using the <- operator on the left side of the channel variable. For example:
value := <-ch
In the above example, we receive a value from the channel ch and assign it to the variable value.
Buffered Channels#
Channels can be buffered, which means they can hold a fixed number of values before blocking the sender. You can create a buffered channel by passing the buffer size as the second argument to the make function. For example:
ch := make(chan int, 3) // Buffered channel with a capacity of 3
ch <- 1
ch <- 2
ch <- 3
Close the channel#
You can close a channel using the close function. Closing a channel indicates that no more values will be sent on the channel. Receivers can check if a channel is closed by using the second return value of the receive operation. For example:
close(ch)
Range over Channel#
You can use the range keyword to iterate over the values sent on a channel. The range keyword will continue to iterate until the channel is closed. For example:
for value := range ch {
fmt.Println(value)
}
Select Statements#
Select statements are used to wait on multiple channel operations simultaneously. A select statement blocks until one of its cases can proceed. For example:
select {
case msg1 := <-ch1:
fmt.Println("Received", msg1)
case msg2 := <-ch2:
fmt.Println("Received", msg2)
case ch3 <- 3:
fmt.Println("Sent 3 to ch3")
default:
fmt.Println("No communication")
}
In the above example, the select statement waits for one of the cases to proceed. If multiple cases are ready, one is chosen at random.
Blocking Operations#
Channels are blocking by default, which means that sending or receiving data on a channel will block until the other side is ready. This property makes channels an effective synchronization mechanism for goroutines.
Example#
In this example, three worker goroutines receive jobs from the jobs channel and process them. The main goroutine sends five jobs to the channel and then closes it.
package main
import (
"fmt"
"time"
)
func worker(id int, ch chan int) {
for job := range ch {
fmt.Printf("Worker %d received job %d\n", id, job)
time.Sleep(time.Second)
}
}
func main() {
jobs := make(chan int, 5)
for w := 1; w <= 3; w++ {
go worker(w, jobs)
}
for j := 1; j <= 5; j++ {
jobs <- j
fmt.Printf("Sent job %d\n", j)
}
close(jobs)
time.Sleep(time.Second * 5)
}