go-102/ Golang concurrency
Make your app concurrent using goroutine and channel
Goroutine works like the thread in java or any other multi-threading programming language, though the internal concept is different. Goroutine is more lightweight than processor thread. It takes little memory (on average 4~8 KB) than regular thread. Goroutines are managed by thread manager in runtime.
Let’s have a look to regular program without goroutine.
In the above program, the second function
bar will execute after the completion of first function
foo . See the example in go playground.
If we want to run these two function in two different thread / goroutine, we can simply put
go keyword before these function.
The above program is executed concurrently (by default goruntime set single logical processor to process, so it’s running concurrently), see it in the playground. We called it bad program though it’s a concurrent program, because we use
sleep to hold the application. The main routine will not wait for the two spawning goroutines. So we can’t see the output. We can use
WaitGroup to do it perfectly, let’s take a look at the example below:
In the above example we used
sync package, you can learn more about it here. In line 11 we called the
Add method passing 2 as integer, here 2 is the number of goroutine. Line 21 & 28 we called
Done method which means the goroutine finished its task. Finally, in line 14 we called
Wait method, this method will hold the main routine until the two routines finish. To learn more about the
WaitGroup visit this link.
By seeing the above picture you can imagine a little about channel. Channel is a pipe or a way to communicate between goroutines. Using channel you can pass data in three way
- bi-directional: usually this type of channel can send and receive data (general signature:
- send-only: this type of channel can only send data (signature:
- receive-only: this type of channel can only receive data (signature:
Let’s take an example of simple channel declaration
In the above example at line 6 we declare a channel (bi-directional unbuffered) type of string, that means it can only send or receives data type of strings. Between line 10–12 we declare an anonymous function in a goroutine, inside the function we send a string message to the channel (see line 11). We received the data at line 16.
We did not define any size of the channel, so by default it is zero size and this type of channel is called unbuffered channel. In unbffered channel the receiver will block until it gets any message and vice versa.
Let’s take a look to the example of a buffered channel
In the above example we declared a buffered channel, to obtain this we simply passed the size as the second argument to
make function. As you know the
unbuffered channel block senders until a receiver is available or vice versa, it will be applicable for the
buffered channel also if the size of the buffer is full. To close a channel we can use
Channel for synchronization
Let’s take a look at a real life example
The above example is trying to solve a real life http request responsibilities. We have two functionalities (one is to save the incoming data to database using
saveToDatabase and other is to cache the data to redis using
cacheToRedis) to complete to make the request done. We spawn two goroutines to do the task concurrently for us. After completing these two tasks then the main goroutine will do it’s task (printing the message in line 37).
If you like the article, please don’t forget to hit the love button
Note: I’ll try to update all of my articles in this series. To get update follow me on twitter or medium. One more thing, if you find any mistake or misleading in these articles please knock me or write a comment. Thank you
If you like my writing please follow me Saddam H.