Avatar šŸ’» Developer by day, šŸŽ® gamer by night | Software Engineer in @Taboola | ā˜• sometimes coffee lover | A good player in call of duty | šŸ“· sometimes love photography

Channel in Golang

A portal to learn about Channel in Golang.

Channel

A channel is a communication technique which allows a Goroutine to communicate with another Goroutine.

Channel


You may notice the ā€œmain routineā€ in above screenshot. As soon as the main routine run of code to execute. The entire program will quit even the other child routine is running.


main routine


Declaration

We can declare channel by writing the following syntax:

var channel_name chan Type

Or We can use a shorthand declaration with a builtin make() function:

channel_name := make(chan string)


Letā€™s see some basic example:

package main

import "fmt"

func main() {
	var channelName chan int

	fmt.Println("Value of the channel: ", channelName)
	fmt.Printf("Type of the channel: %T", channelName)

	channelName1 := make(chan int)

	fmt.Println("\nValue of the channel: ", channelName1)
	fmt.Printf("Type of the channel: %T", channelName1)
}

The following output will be:

// Value of the channel:  <nil>
// Type of the channel: chan int
// Value of the channel:  0xc0000160c0
// Type of the channel: chan int


How to send data with channel?


Sending data with channel


  • Here 5 is the value as input which we are sending through channel with the syntax channel <- 5
  • We can receive the value out of channel (For e.g: when you receive text message and you read it via phone) with the syntax myNumber <- channel
  • To log the channel value fmt.Println(<- channel)


Letā€™s have a quick at this simple channel program:


This program will sum up through channel:

package main

import "fmt"

func main() {
	fmt.Println("Start main function")

	ch := make(chan int)

	go sumValue(ch)

	ch <- 5

	fmt.Println("End main function")
}

func sumValue(num chan int) {
	fmt.Println(5 + <-num)
}

Output:

// Start main function
// 10
// End main function


Another simple channel example with greet message:

package main

import "fmt"

func main() {
	fmt.Println("Start main function")

	ch := make(chan string)

	go greetMsg(ch)

	ch <- "world"

	fmt.Println("End main function")
}

func greetMsg(ch chan string) {
	fmt.Println("Hello", <-ch)
}

Output:

// Start main function
// Hello world
// End main function


Letā€™s have a quick another look at this simple channel program:

package main

import "fmt"

func main() {

   // syntax for channel
   ch := make(chan string)

   ch <- "this is my msg 1"
   ch <- "this is my msg 2"
   ch <- "this is my msg 3"
   ch <- "this is my msg 4"

   fmt.Println(<-ch)
}

Here our channel is unbuffered (we didnā€™t specify any buffer size when make()ing the channel) meaning that they will only accept sends (channel <-) if there is a corresponding receive () ready to receive the sent value. So in this case ā€˜chā€™ is an unbuffered channel and we are attempting to send onto it, but there is no receiver of this channel.

We can fix it by either making the channel buffered or registering a receiver on this channel in another go routine.

So we might see some out error: fatal error: all goroutines are asleep - deadlock!


To avoid this error, we can specify the buffer size:

ch := make(chan string, 4)

We wonā€™t see error here anymore after specifying the buffer size.


Close() function

We can close the channel with builtin close() function. This sets the response with true/false value to indicate no more value will be send to the channels.


Open or close channel value can be checked with the following syntax:

res, status := <-ch


Letā€™s try with one example to check the close function:


package main

import (
	"fmt"
	"strconv"
)

func main() {
	/* Creating a channel */
	ch := make(chan string)

	/* Calling Gorouting */
	go goRoutineFun(ch)

	/*
		when the value of "status"
		receives as "true" that means
		channel is open and it can send and receive data.

		When the value of "status" receives as "false" means
		channel is closed.
	*/
	for {
		res, status := <-ch

		if status == false {
			fmt.Println("Channel is closed:", status)
			break
		}
		fmt.Println("Channel is opened with response:", res, "and status:", status)
	}
}

func goRoutineFun(ch chan string) {
	for i := 0; i < 5; i++ {
		/* This is how we concat the iterated loop value with string */
		msg := "Channel message " + strconv.Itoa(i)
		ch <- msg
	}

	/* Using close() function to close the channel */
	close(ch)
}

We will see the following output:

// Channel is opened with response: Channel message 0 and status: true
// Channel is opened with response: Channel message 1 and status: true
// Channel is opened with response: Channel message 2 and status: true
// Channel is opened with response: Channel message 3 and status: true
// Channel is opened with response: Channel message 4 and status: true
// Channel is closed: false


Hope my contribution will help you to understand this topic. Please feel free to reach out to me on twitter @rajendraarora16 for any queries.

all tags