Hello Folks! Hope you are enjoying Golang Company blogs where we have already written about APi frameworks, data types and others.
Today, we will be covering one of the important concepts in Golang called Go Concurrency. This is where Go lang shines as it gives asynchronous ability to the language. Let’s start
First we will cover Goroutines.
Goroutines is basically a function that is getting scheduled by go scheduler. Go has a scheduler which is created at the run time. Important thing is goroutines do not run in parallel, they run concurrently. It may be confusing so let me explain it more.
Here, l write a small program
If you see, we are creating a function fetchResource() and calling it multiple times. When we run this program it will take 12 seconds or more to complete and Print “I am complete” on the console. This is because every function has a wait time of 2 seconds.
But, if we prepend “go” then all function calls become concurrent and we will immediately get an “I am complete” message on the console.
The above example can also be attained through anonymous function.
Let’s understand by example:
Here we just created one anonymous function and every function inside that because goroutines functions. Here go is prepended to func() which is anonymous as it does not have any name.
One step deeper to Goroutine: Channels
In the above example we saw that func fetchResource is returning a string but we are not using it anywhere.
If we try to write something like below it will not work. This is because function calls are happening outside and concurrently at the run time.
You can think of channels like a tunnel where we put one thing from one end and we receive the information on the other end. It is a way of communicating you may think of channels as a queue.
In General when we declare a channel we append “ch” to the variable so that others can understand that we are using channels.
How do we make channels?
We use make function/keyword to create a channel
Variable name := make(chan datatype)
We write into channel using <-
Let us understand with example:
Comments are self explanatory. However when we run this program. We will get an ERROR!
I purposely did that so that when you will encounter later you understand the reason.
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
All goroutines are asleep why this happens. Now we have to understand the unbuffered and Buffered channels.
In the above example
resultch := make(chan string) is unbuffered channel. And the channel in go lang will always block if it is full. Therefore we are getting the deadlock error as there is no buffer size mentioned and hence it was blocked.
Now how to declare buffered channel,
resultch := make(chan string, 10). Here we have a buffered channel with size 10. Let's run the program again with a buffered channel.
It is running fine as the channel is not full. In our earlier code the moment we are adding string to our unbuffered channel it becomes full and therefore, getting deadlock error. So the channel should not be full as it will block.
So how we can make unbuffered channel work which is blocking us currently. Goroutine is the answer as it will schedule and will not block our channel. Let us understand with example:
This will run without deadlock.
This is a complex thing in Golang. I tried to make it easier for you to understand with lots of code examples. I will dig deeper into channels in other parts. Keep reading. Have any issue or need to develop an application on Golang contact our golang developers.
So the above is more verbose to do. Range is cleaner but just showing you this can also be done.
Check the source code in the linked repository.