Leveraging Golang Concurrency in Web App Development
I first learned about goroutine and channel when I was attending the Golang meetup in GoJek Singapore. In the talk “Orchestrating Concurrency in Go” delivered by the two GoJek engineers Abhinav Suryavanshi and Douglas Vaz, they highlighted the point “concurrency is not same as parallelism” in the very beginning of their talk.
Goroutines and channels are two main things that provide the concurrency support in Golang. To someone who is from .NET and C# background, we are familiar with threads. Goroutines are similar to threads and in fact, goroutines are multiplexed on threads. Threads are managed by kernel and has hardware dependencies but goroutines are managed by Golang runtime and has no hardware dependencies.
Using goroutines is very simple because we only need to add the keyword go in front of any function. This remind me of the async/await in C# which is also concurrent. Async/await in C# implies that if we make a chain of function calls, and the last function is an async function, then all the functions before it have to be async too. On contrary, there is no such constraint in Golang. So when we do concurrency in Golang, we don’t really have to plan on what’s going to be asynchronous ahead of time.
Applying Goroutines
In the web application we built earlier, we introduce a new feature where users can pick the music categories that they are interested at, then it will insert relevant videos into the playlist.
The codes to do the suggestion is as follows.
for i := 0; i < len(request.PostForm["MusicType"]); i++ {
if request.PostForm["MusicType"][i] != "" {
go retrieveSuggestedVideos(request.PostForm["MusicType"][i], video, user)
}
}
Now, if we select all categories and press the Submit button, we will see the videos to be added not following the selection order. For example, as shown in the following screenshot, the Anime related videos actually come after the Piano videos.
YouTube Data API
If you are interested at how the relevant videos are retrieved, it is actually done with the YouTube Data API as follows.
...
youtubeDataURL := "https://www.googleapis.com/youtube/v3/search?"
youtubeDataURL += "part=snippet&"
youtubeDataURL += "maxResults=25&"
youtubeDataURL += "topicId=%2Fm%2F04rlf&"
youtubeDataURL += "type=video&"
youtubeDataURL += "videoCategoryId=10&"
youtubeDataURL += "videoDuration=medium&"
youtubeDataURL += "q=" + area + "&"
youtubeDataURL += "key=" + os.Getenv("YOUTUBE_API_KEY")request, err := http.NewRequest("GET", youtubeDataURL, nil)checkError(err)request.Header.Set("Accept", "application/json")client := &http.Client{}
response, err := client.Do(request)checkError(err)defer response.Body.Close()var youtubeResponse YoutubeResponse
err = json.NewDecoder(response.Body).Decode(&youtubeResponse)
checkError(err) ...