channel in go

c

channel is a communication object using which goroutines can communicate with each other. Technically, a channel is a data transfer pipe where data can be passed into or read from.

It’s more like one goroutine can send data into a channel, while other goroutines can read that data from the same channel.

It’ll be clear once I show you a example

  1. create a channel var channel chan int
  2. use make()

TADA! you created your own . channel

now use make as <nil> is not interesting.

It looks like it’s storing an address. Because it’s actually a pointer. Now lets do something interesting.

package main

import (
	"fmt"
)

func multiply5(c chan int, val int) {
	c <- val * 5
}

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

	go multiply5(num1, 5)
	go multiply5(num1, 4)

	fmt.Println(<-num1)
	fmt.Println(<-num1)

}

Go provide very easy to remember left arrow syntax <- to read and write data from a channel.

I first created a channel num1. Then I called multiply5() with go

var data int
data = <- channel

Now data coming from the channel channel which is of type int can be stored into the variable data of type int.

And it can be re-written using shorthand syntax as below

data := <- channel

I haven’t used wait group but it looks like its working. or is it?

Lets complex things a bit.

package main

import (
	"fmt"
)

func multiply5(c chan int, val int) {
	c <- val * 5
}

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

	//write to the channel
	for i := 0; i <= 6; i++ {
		go multiply5(num1, i)
	}

        close(num1)

	//read from the channel
	for i := range num1 {
		fmt.Println(i)
	}

}

ok. we got a error. But you may be wondering what am I doing here.

  • In the first for loop, I just write into channel as I previously did.
  • In the second for loop, I used range to iterate over the channel to print it. otherwise you have to use <-num1 10 times
  • Its always good to close your channel after writing to it. so I used close()

But whats this error?

well we got upto 9. but something happened in 10. You know what? Let’s wait group it.

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup

func multiply5(c chan int, val int) {
	defer wg.Done()

	c <- val * 5
}

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

	//write to the channel
	for i := 0; i <= 6; i++ {
                wg.Add(1)
		go multiply5(num1, i)
	}
	wg.Wait()
	close(num1)

	//read from the channel
	for i := range num1 {
		fmt.Println(i)
	}

}

And the output is not what we expected.

Ok. we messed up. But what went wrong here?

Well by default channels are blocking. But here we added our own sync. So lets add a buffer size.

change num1 := make(chan int) into num1 := make(chan int, 10)

Here’s the complete code:

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup

func multiply5(c chan int, val int) {
	defer wg.Done()

	c <- val * 5
}

func main() {
	num1 := make(chan int, 7)

	//write to the channel
	for i := 0; i <= 6; i++ {
		wg.Add(1)
		go multiply5(num1, i)
	}
	wg.Wait()
	close(num1)

	//read from the channel
	for i := range num1 {
		fmt.Println(i)
	}

}

And that how you create and iterate a channel.

Happy coding!

About the author

vigneshwar

2 comments

Leave a Reply

By vigneshwar

Most common tags

%d bloggers like this: