How do you create unidirectional channels in Golang?


When working with go language channels there must be cases such as clear communication intent, enhanced safety in communication, encapsulation and more where you need to create unidirectional channels. In this go language article we are going to learn to create unidirectional channels using send only channel method, receive only channel method, using interfaces as well as type conversion methods.

Bidirection channels enables the channel data to be transferred and received. There may be times when you want to impose unidirectional communication, limiting either sending or receiving actions.

Syntax

ch := make(chan<- string)

To declare a send only channel named “ch”.

go sendOnlyChannel(ch, &wg)

To launch a new goroutine we use the “go” keyword. Here the go keyword is executing the SendOnlyChannel() function.

var wg sync.WaitGroup

Sync.WaitGroup, is defined as a variable and is used to synchronize the goroutines.

Method 1: Using Send only channels

This method involves creating a unidirectional channel by specifying the direction of the channel by omitting the receiving arrow (<-) during channel declaration.

Algorithm

  • Create a function named "sendOnlyChannel" that accepts a sync pointer and a send-only channel as parameters.

  • Create a message slice with the strings "Hi," "There," "from," "send-only," and "channel" within the "sendOnlyChannel" method.

  • Utilise the close() method to shut off the send-only channel after all messages have been sent.

  • Announce a sync.Using the "wg" WaitGroup variable, synchronise goroutines.

  • The messages received over the send-only channel "ch" should be iterated over using a for range loop.

  • Use the fmt.Println() method to print each message that was received.

Example

In the following example, we will see how to send the value to another go routine using a send only channel, while the receiving go routine will process the message.

package main

import (
   "fmt"
   "sync"
)

func sendOnlyChannel(ch chan<- string, wg *sync.WaitGroup) {
   defer wg.Done()

   messages := []string{"Hi", "There", "from", "send-only", "channel!"}

   for _, msg := range messages {
      ch <- msg   }

   close(ch) 
}

func main() {
   ch := make(chan string)
   var wg sync.WaitGroup

   wg.Add(1)
   go sendOnlyChannel(ch, &wg)

   for msg := range ch {
      fmt.Println("Received:", msg)
   }

   wg.Wait() 
}

Output

Received: Hi 
Received: There 
Received: from 
Received: send-only 
Received: channel!

Method 2: Using Receive only channel

This method involves creating a unidirectional recieveonly channel by specifying the direction of the channel by omitting the send arrow (<-) during channel declaration.

Algorithm

  • Set up the "fmt" and "sync" packages in your Go environment.

  • Make a "receiveOnlyChannel" function that has two parameters − a receive-only channel (-chan int) and a sync reference.

  • Use the defer statement to signal the function's finish and the wg.Done() method to signal the goroutine's completion inside the "receiveOnlyChannel" function.

  • Use the close() function to end the channel after the for range loop.

  • Print "Receiving complete" to show that the channel has received all values.

  • Use the make() method to construct the receive-only channel "ch" in the main function. Use the close() function to shut the channel after sending all the values.

  • And lastly, dial wg.Before closing the receiveOnlyChannel goroutine, use the Wait() function to wait for it to finish.

Example

In this below example we will see how to send the value to another go routine using a recieve only channel.

package main

import (
   "fmt"
   "sync"
)

func receiveOnlyChannel(ch <-chan int, wg *sync.WaitGroup) {
   defer wg.Done()

   for num := range ch {
      fmt.Println("Received:", num)
   }

   fmt.Println("Receiving complete")
}

func main() {
   ch := make(chan int)
   var wg sync.WaitGroup

   wg.Add(1)
   go receiveOnlyChannel(ch, &wg)

   for i := 1; i <= 6; i++ {
      ch <- i
   }

   close(ch)
   wg.Wait() 
}

Output

Received: 1 
Received: 2 
Received: 3 
Received: 4 
Received: 5 
Received: 6
 
Receiving complete

Method 3: Using type conversion

This method involves creating a unidirectional channel by using type conversion. We can convert a bidirectional channel to a sending only channel or a receive only channel.

Algorithm

  • Add the required packages (fmt).

  • Use the make() function to create a bidirectional channel called ch.

  • Use type conversion (chan- int)(ch) to change the bidirectional channel ch into a send-only channel sendOnlyCh.

  • To send values to the send-only channel, start a goroutine: Use a for loop within the goroutine to iterate from 1 to 6.

  • Use the - operator to transmit each value to the send-only channel sendOnlyCh.

  • Use the close() function to shut down the send-only channel after sending all values.

  • Use a for range loop in the main goroutine to process and receive values from the bidirectional channel ch: Use for num:= range ch to iterate through each value that was received from the channel.

  • Use fmt to print each received value.Println(). Print "Programme complete" to show that the programme is finished.

Example

The below examples involve creating a unidirectional send only channel using a bidirectional channel and show the sending and receiving operations.

package main

import (
   "fmt"
)

func main() {
   ch := make(chan int)

   sendOnlyCh := (chan<- int)(ch)

   go func() {
      for i := 1; i <= 6; i++ {
         sendOnlyCh <- i
      }
      close(sendOnlyCh)
   }()

   for num := range ch {
      fmt.Println("Received:", num)
   }

   fmt.Println("Program complete")
}

Output

Received: 1 
Received: 2 
Received: 3 
Received: 4 
Received: 5 
Received: 6 

Program complete

Conclusion

In this article we have discussed a variety of Go Language channel creation techniques. Unidirectional channels offer a strong method of communication between goroutines while mandating particular data transmission or reception patterns. The method shown above can be used for designing API’s involving data passing, to propagate messages to multiple channels. These channels help in enhancing readability and reduce misuse of information.

Updated on: 05-Jul-2023

141 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements