Concurrency with Go
In case you are landing here directly, it’s suggested that you go and read through this for fundamentals.
In this blog, we shall be looking at following concepts :-
- Building concurrency with GoRoutines.
- Communication between GoRoutines using Channels.
- Demonstrating Blocking behaviour of UnBuffered Channels in Go.
- Closing the Channels to handle infinite records in Go.
- Demonstrating the concurrent approach to fetch data using Channels.
- Working with Multiple Channels.
Question:- What are Channels in GO ?
Answer:- Channels are typed, one-directional pipes. You send values at one end and receive them in the other end. If you try to receive and there’s nothing in the channel, you’ll get blocked.
Question:- What are the various kinds of Channels available in GO ?
Answer:- There are actually two kinds of channels :-
- Unbuffered → When you push a value through an unbuffered channel you’ll get blocked until someone receives on the other hand.
- Buffered → If you send to the buffer channel until the capacity is filled, you won’t block. Buffered channels are somewhat like bonded queues.
Each buffer channel has a capacity. After the capacity is full, ascent to a channel will be blocked.
Question:- Can you showcase an example with Buffers in GO ?
Answer:- Here is an example, we created the simple Integer buffer channel :-
- In line #9, we create a channel using the make builtin function. This channel is a channel of integers.
- At line #12, we are trying to receive from the channel and print out here.
Question:- In the output section, we can see that, it says :- All goroutines are asleep, there is a deadlock. Can you explain this ?
Answer:- This is because nothing was pushed to the channel and that’s why we are sort of blocked here, because of deadlock.
Question:- Let’s send some value to this channel via some GoRoutine ?
Answer:- Here is the example :-
- At line #11, we create a go routine that sends a value to the channel in below snapshot.
- At line #17, we receive the value from the channel and print out the value.
Question:- Can you demonstrate the behaviour of being Blocked, in case of UnBuffered Channel ?
Answer:- Let’s see how we’re blocked on multiple send/receive. See here, At line #23, we are trying to send the data to the channel, but because there is no consumer, that’s why we are totally blocked and only one particular record could be sent. Thats’s all and our program terminates, after sending one event/record to our channel :-
Question:- Let’s also have the consumers, consuming from the UnBuffered Channel, parallely :-
Step #1.) We create a go routine that runs three times, every time sending a value to the channel and sleeping for a second.
Step #2.) In the main method, we are also receiving three times from the same channel and print out what was received.
In the output section, we see following order. Everything is in order, first we send to the channel and then we receive from the channel.
- sending zero and receiving zero.
- sending one, receiving one
- sending two, and receiving two.
Question:- How does we handle a situation, where we don’t know the number of items in the channel ?
Answer:- In that case, here is the demonstration for the same :-
- At line #19, the sender can signal it is done by closing the channel.
- At line #22, this time we are going to use the builtin range keyword to iterate over the data being present in this channel, and every time we will print the value we received.
And again, we see sending and receiving of the data-packets is well in order.
Question:- Demonstrate the concurrent approach of parallelising the data-fetching behaviour, using Channels ?
Answer:- Here again, we shall be considering the same above example, where we shall like to query a bunch of URLs, and see whether they return HTML, JSON, XML, or other format.
Step #1.) First, we declare a slice of strings, for which we shall be finding the content-type in a parallel way :-
Step #2.) Next, we create a channel of string type using inbuilt function “make” :-
Step #3.) Next, we now invoke the function, returnType, which does an http call, and then, looks at the header and emits it out to the channel that we are passing as an argument.
Step #4.) Now, we consume the data from the same channel, whatever data has been pushed to it shall be printed to the console :-
Step #5.) Let’s have a look at the core function “returnType”, which shall first hit to the concerned url and emit the content-type header value to channel :-
Step #6.) Let’s now verify the program, by executing the same :-
Net total time taken is around 2.86 seconds along with all the data being printed now.
Question:- How do we work with multiple Channels together ?
Answer:- The built-in select function allow us to work with several channels together. Every time a channel with selecting on become free, either for sending or receiving, you’ll do an action on this channel.
- At line #9, we’ll create two channels, channel one and channel two. And then we run a routine, that sends a value to channel two.
- Now we can run a select statement from whatever channels, from where data is expected. In our case, we expect value from channel two, and we print out that we got the value from channel two, and another case, we get the value from channel one, and we print that we got the value from channel one.
Question:- What’s the usual use-case of using Channels practically ?
Answer:- One of the common uses for select is to implement timeouts. Here is the example for the same :-
- At line #11, we’re going to make a channel.
- At line #12, we are creating a routine → That sleeps for 100 milliseconds, and then sends a value on the channel.
- And then we do a select. One case, we get the value from the output channel, and we print it out.
- The other channel that a value will be sent on it after 20 milliseconds. And we print out the timeout, if we got the timeout.
Note, that this does not kill the go routine. It will work in the background, but since go routines are cheap, this is not a big deal.
That’s all in this section. If you liked reading this blog, kindly do press on clap button multiple times, to indicate your appreciation. We would see you in next series.
References :-
- https://adityagoel123.medium.com/beginners-guide-to-go-lang-part2-bbfa02c858c9
- https://adityagoel123.medium.com/benchmarking-in-go-aaa56a6e2dba
- https://adityagoel123.medium.com/test-driven-development-in-go-689a671eae4a
- https://adityagoel123.medium.com/beginners-guide-to-go-lang-part1-4bbd96e6d97
- https://adityagoel123.medium.com/go-lang-hands-on-part-3-3d0b161d6ab9
- https://adityagoel123.medium.com/in-conversation-with-go-langs-datatypes-part2-fa0b7ca98725
- https://adityagoel123.medium.com/in-conversation-with-go-lang-part1-57753b03072e
- https://adityagoel123.medium.com/installing-verifying-go-in-vs-at-mac-ef15a909d8fa
- https://github.com/adityagoel123/GoLangBasics
- https://stackoverflow.com/questions/54591045/go-test-function-returns-undefined-function
- https://github.com/adityagoel123/GoLangBasics
- https://github.com/adityagoel123/GoLangGuide