Golang / Go Crash Course 05 | Building an API Mashup using Goroutines and Channels

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
What's going on guys? In this video we are going to use goroutines and channels to build an API mashup pulling data from two different APIs.... I created a Golang cheat sheet that includes some examples on goroutines and channels and also some examples on interfaces,structs, error handling and a lot more! you can download the golang cheat sheet from the link in the description below (pragmaticreviews.com) Remember to share, like, and subscribe to the channel and let's get started.... so this is going to be the result after the mashup of the two APIs that we're going to integrate using goroutines and channels so these four attributes: the identifier, the brand, the model and the year are going to be extracted from this endpoint: https://myfakeapi.com/api/cars/1 and these are the attributes that we are going to extract the identifier, the brand, the model and the year and these three attributes: the first name, the last name and the email we are going to extract those from this endpoint: https://myfakeapi.com/api/users/1 and we're going to extract this first name attribute, the last name and the email...okay so I already created the server I'm using the HTTP router that we created on a previous video and I've added this endpoint that is going to use this resource or this URI and it's going to use this function within the car details controller that is actually this one and what it's going to do is it's going to delegate to the car details service and it's going to call this function that is going to return an structure that we are going to define that is going to basically represent this output that we are going to return when our API is invoked specifically we are using the Chi router and here we have the controller where we are passing the service as a parameter... let's get started working on the data structures that are going to represent not only the output after the mashup of the external api's but also the data structures that are going to represent the attributes that we want to extract from those external api's so first let's start working on these four attributes that are part of the first API so I'm going to create a new file here this is going to be car.go the package is going to be entity and the struct is going to be a car struct and if we go back to the response of this external API we're going to see that we have a car and within this element we have the attributes that we want to extract so we need to create another structure let's call it CarData (type CarData struct) and here we have to add the four elements: the identifier it's gonna be an int here we define the attribute name.... and we also need to add the rest of the attributes the brand, the model .... it's gonna be ID it's gonna be brand, it's gonna be model sorry this gonna be a string it's gonna be the string as well and the attribute in this case is car_model and then we have the year that's going to be an int and in this case the attribute name is car_model_year like this okay so this is the structure and we need to embed the structure here so this is the structure that we just created and now we need to add this wrapper element so we need to embed this struct within this one...in this case the field name is going to be Car like in here okay now we have the struct that is going to represent the output of the first API now let's create the structure that is going to represent this output (the second API) so let's call it owner.go the package is going to be entity... type owner struct and here we need to do something similar to the car because we have this element that is wrapping the attributes that we need so we're going to create another struct here there's going to be OwnerData and this is the struct that is going to include the attributes that we need to map so we have first name, last name and email so this is firstname string and field name is first_name like this the second one is going to be last name and this third one is going to be the email and that's the field that we need to map okay and here we need to embed this struct that we created and it's going to be User like this let's copy that and we have our structure created for the output of this second API and now we are going to create the structure for this output for the mashup API that we are implementing so we are going to call it CarDetails car-details.go and here the package is going to be entity "...type CarDetails..." and here we are going to have all these elements right we can grab this one from here I forgot to add "struct" here okay we have ID, brand, model and here ID, brand, model here and the fields we want these fields we want ID, we want brand and this is going to be model and it's going to be model year and we need to add the details of the owner of the car let's say and we can extract those from here and for this last three attributes we want to assign owner_firstname owner_lastname and owner_email like this okay now we have all the data structures that we need and let's move on to the service so this service is going to return entity and the struct that we already created that is CarDetails and I need to import the entity package "import entity" okay and the interface is going to also return that type okay this method what is going to do is it's going to create a Goroutine to get data from the first API that is this one..... another Goroutine to get the data from the second API which URL is this one and then we are going to create two channels "create channel to get the data.... "create channel this should be userChannel, sorry, carChannel the first one....and then we are going to create the ownerChannel to get data from endpoint 1 and this is going to get the information from the endpoint 2... so let's say goroutine the goroutine is actually going to call endpoint 1 and this goroutine is going to call endpoint 2 so these are going to be 2 asynchronous operations that we want to create a (to run on a new) thread so they can run in the background and once we get the result we're going to receive that result here in the channels that we are going to create so this is pretty much what this method is going to do so let's create a service to call the endpoint number 1 so this is going to be the car service that is going to extract the information from this endpoint so let's go to the service folder and let's create a new file let's call it... car-service.go the package is gonna be service and we are going to create an interface here car service and the only method that we are going to declare here is going to be the fetch data method okay and we need to create a structure to implement that interface let's call it fetch car data service like that I forgot to add the struct here okay and we need to create our constructor function it's going to be new car service and it's going to return a reference to this struct and I need to declare the type here that is CarService okay and now I need to implement actually this fetch data function so func it's gonna be....I need to pass the struct here to make it implement this function it's going to be fetch data and here what we're going to use is an HTTP client that is going to call that it's going to invoke this URL so I'm going to copy this URL and I'm going to create a constant here car service URL like that and here I need to use I'm going to create a client that's gonna be http.Client{} ...like that I'm going to print just to show that I'm calling that endpoint fetching the URL and I'm going to pass the URL car service URL this is fmt.Printf... like that and here what I need to do is I need to call the external API and here I need to handle the response and I'm going to ignore the error and I need to use client that get and I need to pass the URL that is this one okay and after that what I need to do is I need to write the response to the channel and this is going to be done once I declare that channel the channel needs to be shared between this car detail service and this car service and this is pretty much what we need to do to get the data from the first API that we want to mashup and now I'm going to create another service that is going to be pretty similar to this one it's going to be the owner service and pretty much the only thing that is going change is the URL so I'm going to copy this one and I'm going to adapt it, I'm going to rename it... this is going to be... owner-service.go let's rename this we're going to use the same fetch data function this is going to be owner service URL it's gonna be users let's check yes "..../users/1" and it's going to be fetch owner data service let's copy this let's copy this interface here and this is going to be new owner service and I need to copy the structure here to make it implement this function and here I need to change the URL for this one and here and I think that's pretty much for this owner service so we have the car service that is going to get the data from this endpoint and then we have this owner service that's going to fetch the data from this other endpoint okay now I need a reference to those services that I just created because I need to use those services here okay I'm going to add those variables to create those references so first I'm going to use the car service it's going to be a car service interface and I need to use the constructor new car service to get a reference to that service and I'm gonna need the owner service that is going to implement the owner service interface and I need to create a new instance by using the new owner service function like that and also I need two channels here so I need a car data channel here I'm going to receive the HTTP response so I need to use the make function and here I'm going to declare the channel like this chan and it's going to be a reference to *http.Response like that and something similar to the other API so this one is going to be owner data channel where I'm going to receive the data related to the owner of the car okay so this is pretty much what we need to start working on our get details function so here I'm going to use a Goroutine this is gonna be go using this keyword I'm going to create a new thread and that thread is going to run this method carService.FetchData() and something similar for the owner service in another go routine ownerService.FetchData()... okay and now let's go to the car service and here I need to write a response to the channel the channel is car data channel and I can write to that channel like this and I pass the response so once I get the response from this API that is actually this URL I pass or I write the response to this car data Channel and something similar is going to happen here on the owner service once I get the response from this endpoint I'm going to write the response to the owner data channel like this I'm going to remove the "todo" here and I'm going to remove the "todo" here okay let's go back to the car details service I'm going to create a function that is going to read the information from the channel and it's going to decode that data from JSON to the "object" that we need so let's do that actually we need to create two functions one for the car data and the other one for the owner data so the first one is going to be func getCarData() and here I'm going to return entity.Car or an error in case we have any errors so first I'm going to read the information from the channel and I can do that like this I create this variable ":=" ...and here I specify what is the channel that I want to read from in this case it's gonna be car data Channel and I'm going to create a variable here that's going to be the car entity.Car and now I'm going to decode the response that I received here from the channel so it's going to be Shea sound I knew the coder and here I need to pass r1.Body like that and here going to call the encode function, sorry! the decode function because I receive a JSON here...decode function and I need to pass a reference like this to the car variable where I'm going to create the object okay and here I need to handle this error in case we have any errors decoding the body and here we are going to check if err is not Nil I'm going to print an error... ...let's use the Error() function here I forgot to add the function print like that and I'm going to return car and error and if we don't get any errors I just return car and nil... like that and the other function to get the owner data it's gonna be pretty similar so I'm going to copy this and I'm going to adapt it for the owner data so this is gonna be getOwnerData() and this is gonna be entity.Owner like that and here the channel is going to be owner data channel like that and here I'm going to create a variable that is going to be owner entity.Owner and here is not car, is owner like that and here I'm going to return the owner and the same if we don't get any errors I'm going to return the owner and nil as the error okay now let's use these functions from here so here I'm going to receive the car and an error I'm going to ignore the error and here I'm going to use the get card data function and something similar for the owner owner and I'm going to ignore the error and I need to use here the get owner data function let's check if everything is okay........ yeah I think we are good okay let's move on I'm going to remove these comments and now I need to return this structure okay let's grab the attributes from here okay the identifier is going to be car.ID the brand is going to be card.Brand the model is going to be car.Model the year is going to be car.Year okay and the first name is gonna be owner.FirstName the last name is going to be owner.LastName like that and the email is going to be owner.Email okay I think we're good okay I'm going to create a test really quick here so this is gonna be car-details -service_test.go I'm going to use the same service package and here I'm going to create a function that is going to be TestGetDetails() I'm going to pass t and the reference to the testing library *testing.T like that car detail service like that and I need to use the constructor here new car Details service and here I expect to get the car details and I need to use the getDetails function from the car details service so this is gonna be... carDetailsService.GetDetails() like that I'm going to it put this in a variable here yes like that and here I'm going to add some assertions first I need to import the testify assertion library I'm going to do that so this is.... "github.com/stretcher/testify/assert" so here we can use assert.NotNil() and I'm going to check that the car details are not empty and I'm going to check a couple of elements so I'm going to use equal .... assert.Equal here I need to pass the test the expected value in this case I'm going to check that the identifier is 1 and here I need to pass carDetails.ID and something similar for a couple of attributes let's say brand and the year sorry the year so here I expect the brand to be Mitsubishi and the year I expect it expect it to be 2002 like that okay let's run this test okay like that okay let's run this again and the test is passing okay let's quickly debug it to see just to check what is the information that we get here so I'm going to click here on "debug test" and if we go here to the car details we're gonna see that we get the identifier as 1 the brand as Mitsubishi the model as Montero the year as 2002 ,first name last name, and email and are basically the information that we got from here right the identifier, the brand, the model and the year and the same for the rest of the information the first name like in here, the last name like in here and the email the same as this one let's run this "go run *.go" okay and now we have our server let's go back so we have our server running on this port so I'm going to create that request http://localhost:8000/carDetails so if we run this we should get a response that we expect... yes we get the id, brand, the model, the year, the owner first name the owner last name the owner email and this is the same structure that we defined here at the very beginning of the video ID, brand, model, year, owner first name, owner last name okay that's pretty much all I have for today thank you for watching...remember to download the free Cheat Sheet for Golang (pragmaticreviews.com).... and I see you guys in the next video, take care, bye!
Info
Channel: Pragmatic Reviews
Views: 3,294
Rating: undefined out of 5
Keywords: golang goroutines channels api mashup, golang crash course, golang tutorial, go tutorial, go goroutines channels tutorial, goroutines, golang channels, golang api mashup, go channels and goroutines, go channels explained
Id: dihX12GkBnc
Channel Id: undefined
Length: 33min 22sec (2002 seconds)
Published: Sat Jan 18 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.