Golang program to takes two unidirectional receiving channels and a sending channel


Unidirectional channel is a type of channel that will be either used for sending data or receiving data, but can’t be used for both. In this Golang article we will explore a Golang program that takes two unidirectional receiving channels and a sending channel using select statement as well as using a fan-in pattern method. We will provide code examples with algorithms and output of the code.

Method 1: Using Select Statement

This method allows you to handle multiple channel operations simultaneously and selecting the one which is ready to be processed.

Algorithm

  • Make three channels: channel one, channel two, and out.

  • Launch a goroutine to run the combineChannels function, supplying as arguments channel1, channel2, and out.

  • Inside the combineChannels function, do the following −

    • Use a range loop to receive values from channel 1 and transmit each value to the out channel.

    • After channel 1 is closed, use a range loop to receive values from channel 2 and transmit each value to the out channel.

    • Shut off the out channel.

  • Inside the main function initialize channel1, channel2, and out channels in the main.

  • Use a range loop to receive values from the out channel and print each received value.

Example

The example given below demonstrates a way to combine values from multiple channels to a single channel using goroutines.

package main

import "fmt"

func combineChannels(channel1 <-chan int, channel2 <-chan int, out chan<- int) {
   for val := range channel1 {
      out <- val
   }

   for val := range channel2 {
      out <- val
   }

   close(out)
}

func main() {
   channel1 := make(chan int)
   channel2 := make(chan int)
   out := make(chan int)

   go combineChannels(channel1, channel2, out)

   go func() {
      channel1 <- 1
      channel1 <- 3
      close(channel1)
   }()

   go func() {
      channel2 <- 2
      channel2 <- 4
      close(channel2)
   }()

   for val := range out {
      fmt.Println(val)
   }
}

Output

1
2
3
4

Method 2: Using Fn-In pattern

Fn-In stands for function in function, is an adaptive way of managing values received from many routes. It allows you to manage the values from many channels separately and carry out various actions for values of each channel.

Algorithm

  • Create three channels: channel1, channel2, and out.

  • Create a sync.WaitGroup called wg with an initial count of 2.

  • Launch two goroutines: Goroutine 1: mergeChannels(channel1, channel2, out, &wg)

  • Inside mergeChannels: Create another sync.WaitGroup called mergeWG with an initial count of 2.

  • Launch two goroutines −

  • Decrement the count of wg using wg.Done().

  • Create a slice called results to store the merged values and Iterate over the out channel using for val := range out: Append each received value to the results slice.

  • Sort the results slice in ascending order using sort.Ints(results) and Iterate over the sorted results slice and print each value.

Example

The code given below demonstrates a way to merge values of two input channel to a single output channel. The values that are merged are then sorted and displayed.

package main

import (
   "fmt"
   "sort"
   "sync"
)

func receiveFromChannel(channel <-chan int, out chan<- int) {
   defer close(out)
   for val := range channel {
      out <- val
   }
}

func mergeChannels(channel1 <-chan int, channel2 <-chan int, out chan<- int, wg *sync.WaitGroup) {
   defer close(out)

   var mergeWG sync.WaitGroup
   mergeWG.Add(2)

   go func() {
      defer mergeWG.Done()
      receiveFromChannel(channel1, out)
   }()

   go func() {
      defer mergeWG.Done()
      receiveFromChannel(channel2, out)
   }()

   mergeWG.Wait()
   wg.Done()
}

func main() {
   channel1 := make(chan int)
   channel2 := make(chan int)
   out := make(chan int)

   var wg sync.WaitGroup
   wg.Add(2)

   go mergeChannels(channel1, channel2, out, &wg)

   go func() {
      defer close(channel1)
      channel1 <- 1
      channel1 <- 3
   }()

   go func() {
      defer close(channel2)
      channel2 <- 2
      channel2 <- 4
   }()

   go func() {
      wg.Wait()
      close(out)
   }()

   var results []int
   for val := range out {
      results = append(results, val)
   }

   sort.Ints(results)

   for _, val := range results {
      fmt.Println(val)
   }
}

Output

1
2
3
4

Conclusion

In this article we have discussed two different methods, the select statement and fn-in method in Go language, which allow us to merge values from two unidirectional receiving channels into a single sending channel. This approach is very helpful while processing data parallelly, or in situations where you need to work on a continuous stream of data. The specific application will depend on your requirement.

Updated on: 05-Jul-2023

212 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements