Advertisement
In the previous blogs about Golang Channel, we learned about Types of Channels and Deadlock. This time we are going to learn about Golang Channel Range and How to close a Golang Channel using the Close function. we will also learn how to defer the close function.
Read Golang Channel Deadlock.
Golang Channel Range Deadlock
for i := range {}
Example:
func main() {
ch := make(chan int, 50)
wg.Add(2)
go func(ch <-chan int) {
for i := range ch {
fmt.Println(i)
}
wg.Done()
}(ch)
go func(ch chan<- int) {
var i int
i = 17
ch <- i
ch <- i + 18
wg.Done()
}(ch)
wg.Wait()
}
Output:
17
35
fatal error: all goroutines are asleep – deadlock!
While iterating over the channels in Golang, we got the values of both the sending channel but also faced deadlock. But Why?
The Answer is the loop doesn’t know when the Golang channel ends as there is no end condition for the loop and data can flow from the channel every time and thus deadlock occurs.
The solution is to close the channel and this will tell the loop to stop iterating as the channel is closed and no deadlock will occur.
Close Golang Channel
Closing Channel Syntax:
close()
func main() {
ch := make(chan int, 50)
wg.Add(2)
go func(ch <-chan int) {
for i := range ch {
fmt.Println(i)
}
wg.Done()
}(ch)
go func(ch chan<- int) {
var i int
i = 17
ch <- i
ch <- i + 18
close(ch)
wg.Done()
}(ch)
wg.Wait()
}
Output:
17
35
The close channel function notifies the for a loop about the closing of channel and thus the loop also breaks.
One thing to keep in mind, close the channel at the end and don’t pass any value after closing the channel.
If any value will be passed after closing the channel the program will panic.
Example:
ch <- i
close(ch)
ch <- 19
panic: send on closed channel
To Recover from the Panic in Golang use the Recover function as a deferred statement.
Let’s Understand how the for loop knows that the channel is closed.
Actually, we can pull out two variables from the channel, one is the value and the other is a bool value (comma OK) which tells that the channel is open or not. If the channel is open the bool value returns true and false if the channel is closed.
Example:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup = sync.WaitGroup{}
func main() {
ch := make(chan int, 50)
wg.Add(2)
go func(ch <-chan int) {
for {
if i, ok := <-ch; ok {
fmt.Println(i)
} else {
break
}
}
wg.Done()
}(ch)
go func(ch chan<- int) {
var i int
i = 17
ch <- i
ch <- i + 18
ch <- 13
ch <- 19
close(ch)
wg.Done()
}(ch)
wg.Wait()
}
Output:
17
35
13
19
Defer Close Function
Close the channel after making it, using the defer function. This will be executed when the main function will be about to exit in this way the channel will be closed and no resources will be taken.
Example:
go func(ch chan<- int) {
defer func() {
close(ch)
}()
var i int
i = 17
ch <- i
ch <- i + 18
ch <- 13
ch <- 19
wg.Done()
}(ch)
wg.Wait()
Learn more about Channels in Golang from the official Documentation.