Concurrency in Golang using Channels

Shravan C
4 min readDec 6, 2019

As always, introduce yourself? Okay why not, Golang is an open-source programming language that makes it easy to build simple, reliable and efficient software. My version to it from so far experience in Golang is, a very strict language that will not let you define a variable and not use it and concurrency is the main theme that this language is built upon. And a silly joke of mine for the love of Ruby language, Golang does this strict check on variables and libraries imported, Python does this indentation check and the Ruby language it's so cool and chilled it lets you program the way you want.

Moving on, introducing Concurrency, Concurrency means multiple computations are happening at the same time. So my version to it is, concurrency is a way of programming and thinking/structure the code to perform a particular task concurrently. This is completely out of the context with the number of processes that are there in the hardware. It is about programming it to be concurrent. Stressing on concurrent to actually clarify on another friend of concurrent that is Parallelism. Parallelism is about executing a set of instructions at the same time. It is in the context of OS. Concurrency is one way of imposing/triggering parallelism. Giving extra work for OS to handle. Concurrency is the boss here to give instruction to OS asking to run it in parallel, depending on the resource available, OS oblige to the Boss’s instructions.

At last, pulling the curtain down for out Channels, Channels are a typed conduit through which you can send and receive values with the channel operator, <-. Okay again adding to it, Channels are basically a way of communicating with goroutines. It can be understood in many different contexts, like, consider a dog waiting for its bowl to be filled with food by his owner or you waiting for a mail to receive in your email account to make a decision on something else..etc Buffered channels are basically like a single dog with two bowls, owner can fill in one bowl first and dog starts consuming it and at the same time owner can fill in something else in the other bowl as well. Here, dog and owner are the processes, the bowl is the channel and the food is the message passed between the dog and the owner

Suit up for the coding part. Producer and Consumer problem it is!!

Approach, Channels and go is used and Mutex is not considered. And three channels are used to make it synchronous. Implementing the stack(FIFO). Diving into the code:

package mainimport (
"fmt"
"time"
)
type Stack struct {
Data []interface{}
Size int
}
func (s *Stack) Len() int {
return len(s.Data)
}
func (s *Stack) Push(value interface{}) {
s.Data = append(s.Data, value)
}
func (s *Stack) Pop() {
if s.Len() > 0 {
s.Data = s.Data[:s.Len()-1]
}
}

Implementing the stack using struct and there are Push and Pop which is obvious, one to update the data at the end and to remove the data at the end respectively.

func producer(s *Stack, c1, c2 chan string, number int) {
for i:=1; i<number+1; i++{
s.Push(i)
//fmt.Println("produced")
c1 <- "produced"
<-c2
}
close(c1)
}
func consumer(s *Stack, c1, c2, c3 chan string){
for _ = range c1{
//fmt.Println("consumed")
c2 <- "consumed"
}
close(c2)
c3 <- "completed"
}
func main() {
var s Stack
var number int
var c1 = make(chan string)
var c2 = make(chan string)
var c3 = make(chan string)
fmt.Println("Enter the number of producers you want: ")
fmt.Scanf("%d", &number)
fmt.Println("Now we Produce :")
start := time.Now()
go producer(&s, c1, c2, number)
go consumer(&s, c1, c2, c3)
<-c3elapsed := time.Since(start)
fmt.Println("Time taken is: ", elapsed)
}

An explanation for this working? Yup, why not...

Thanks to Jam Board for this tool(https://jamboard.google.com/d/1qOb5Ln0Tz5tQfLAOpWEtVMd-88nm9BN7Yb0M3ztqas4/viewer)

So, the Producer updates the channel C1 and Consumer listens to it and waits for the message. Once it is received it pops and then informs/communicates with the Producer saying consumed please produce back again. This process continues until the producer is left nothing to produce and then closes the channel. Once the C1 is closed and it is all being consumed C2 is also closed by the consumer. Then this happens:

https://jamboard.google.com/d/1AtJ26H1GNAEzillVJtJ6WrXzyx68VQs9Fgd0LERjhcE/viewer

Finally, in order to get back to the main function C3 channel is defined and its purpose is served by the Consumer at the end of the Producer-Consumer cycle. Once the message “completed” is passed to the C3 channel it returns to the main and then finishes the rest of the operation.

And it is what it is. Golang and channels are fun to play with and Golang is very cool in the sense it detects the deadlocks beforehand. Only this strictness looks cool :). Github repository for the code and many more.

Conclusion it is, there are many different ways of implementing producer and consumer, like passing a channel to a channel as a message, so explore more on this and have fun sharing…There is a saying for Golang, “Don’t communicate by sharing a memory, instead share memory by communicating”. It is to say share/communicate the pointers over channels or the address of the memory instead of communicating when to access the memory(mutex comes into the picture). Last but not least please donate a clap if you like it :3

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Shravan C
Shravan C

Written by Shravan C

Software Engineer | Machine Learning Enthusiast | Super interested in Deep Learning with Tensorflow | GCP

No responses yet

Write a response