Golang Channel Range and Close Channel

Golang Channel Range and Close Channel

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 Close function. we will also learn how to defer the close function.

Read Golang Channel Deadlock.

Golang Channel Range Deadlock

for i := range <channel_name> {}

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(<channel_name>)

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 loop about 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 Recover function in 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.

Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *