Go api with docker, postgres and chi router [UPDATED]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up YouTube Welcome to another video today we're gonna be uh re-recording the um coffee API um application that we created on the other video um in goldling I'm gonna recreate this because the other one was a little bit long um it was a little bit unplanned so I did it on the go and that's why it took like four hours and something so essentially I redid it I did uh I added a few improvements here and there and now that I have it um organized and planned this should take way less hopefully it goes below the two hours Mark but we'll see uh but without further Ado let's go ahead and start with the application so what we're going to be doing here as you can see is start from scratch um I'm gonna go ahead and do my create directory I'm gonna call this coffee app so let's go inside of our application I'm gonna be doing the following I'm gonna create the server side but also the client side hopefully um you know this series goes a little bit further and we can also implement the the front end and hence why we're going to be creating both so first of all I'm going to do my server directory so make directory uh coffee server and then um I'm gonna go ahead and create my client I'm gonna use next.js install command so I believe you can just use at latest uh actually let's go here get started installation yep so I'm going to do here MPX great next app latest um sure let's install all the layers thing uh what is your project name this is going to be coffee we don't love and I'm gonna put client typescript yes yes and yes Tailwind yes we're gonna be using Tailwind Source directory yes I like that uh would you like to use the app router no we're going to be using the old router um I don't need to customize any um default stuff import Alias or whatever so that is going to be created and whatnot um I'm just gonna pause at me what that creates all right so there it is it's created so now we should be having those two folders the coffee client and the coffee server uh either way today we're not going to be doing a lot of uh client or not in this video at least so I'm gonna go into my mvim and let's start with the server so the first thing that we want to do is set up our make file uh where inside of our main file we're going to set up the docker container and database uh some um commands that will be we will be using and make sure that we can you know have our migrations our tables and whatnot so let's start with that so the first thing that I'm going to do um I'm going to create my git ignore file so there's my file I'm going to ignore the dot EMB and I'm also going to ignore let's see if I'm missing something else it ignore um that should be that should be fine okay so we have those two things um the file and the and the git ignore file the 30mb ignore and the ignore I'm going to create my.dmv inside of my.dmv um so this is very important I'm going to be creating uh let me see where did I leave this we're going to be creating the following variables so the first one is going to be the port uh later when we start the application we're going to make making use of that also very important Docker container name which I'm also I'm only going to be calling it DB Docker container container so this is going to be the name of the docker container not not the database so YouTube uh YouTube TV container then we're gonna have the DB name so this is going to be the name of the database uh I'm gonna put YouTube coffee DB the user root password secret again this is not Ultra secure but since this uh learning tutorial we really don't care for now obviously when we create a production application these variables will be more secured you know user and password will probably be different will definitely be different uh the database Port will be the default for postgres we're going to be using posters so five four three two and the binary so the name of of our compile file will be the following I'm going to call it coffee underscore API all right now we're going to be saving that okay cool so now let's go ahead and create our make file so here we're going to be putting all the instructions uh you know to create our binary to start Docker containers to stop Docker containers to initiate migrations everything will be there so let's go ahead and start with our make file so the first thing that I'm going to do is to include the dot EMB file so we're going to be pulling the variables from there that way we can add our make file to our repo but we're not exposing any important information into our DB into our DBP into our GitHub repo so this is a command that I like to put because it's I think it's very useful this will stop any containers that are running so stopping other Docker containers um so we're going to be doing the following we're going to be listing any Docker container and if we do happen to see any Docker container running then we're gonna be uh stopping that Docker container so we're gonna Echo found and stopped containers and here we'll be doing the stopping so stop Docker PS and lastly if there are no Docker containers running and actually the echo we also need to escape it with the following otherwise we'll get some errors if we don't do the the backslash otherwise if there are no containers running we put no containers running okay so we'll we'll look like that so let's make sure that this command works so I'm gonna do make a oh I need to be on the server so see the coffee server make stock containers and I probably have one error probably here on the echo I'm using the semicolon probably okay let's try that again and there you go no containers running perfect uh the second thing that we want to do is to create um create our Docker container so create container it's going to be done in the following way I'm going to be doing Docker run I'm gonna give it an explicit name uh referencing our DB Docker container and we can see what we have let me see if I can open the okay I'll probably have to do this there you go so we have the TV uh Docker container okay uh when we created we're going to be designating a port 5432 on our local machine and also on the virtual machine or in the docker container actually I may need to close this so we have more screen okay so we're gonna set the postgres user equal to the user variable that we have in our DOT EMV same for the password I'm gonna have to put postgres password equal to password and lastly the type of image that we're going to be using which is a 12 Alpine Linux image all right so uh we're going to be having that so I'm gonna I'm gonna pull up the uh Docker desktop application and right now I have no images running so I'm gonna do the following I'm gonna run my create container command and you should be able to see this uh so when you see that it means that you create a correctly the image and here as you can see I have the YouTube TV container um successfully created so that is how we create our talking container uh so now what we're going to be doing is creating the database inside that Docker container so great to be will be equal to Docker execute slash it and I'm going to pass the name of the docker container I'm gonna pass the the variable sorry or you know the name of the container that we just created we're going to execute the command create DB and the username will be the same as the one that we use with the user variable uh same for the owner foreign we're going to call our database whatever we designated with our DB name variable in our DOT EMV okay so let's go ahead and make sure that this works so I'm going to run the create DB and it all seems to be fine perfect so now we just want to make sure that um this is actually running so I'm going to be a I'm going to be opening table plus and you can use any software uh you don't have to use table plus you can use postgres manager you can use you know there's I think there's b b keeper Studio whatever um whichever database Connection Manager do you want to use go ahead but we want to make sure that we can connect so host by default that's fine Port I'm not gonna specify either because the default is 5432 username root password secret the database is the one that we used um the database name is the one that we used okay I have to open it manually Okay so um YouTube coffee TV okay so YouTube coffee TV and SSL mode we're gonna put disabled for now so we're gonna connect and here you go it's completely empty we don't have anything but it is connecting perfect so you should be able to connect and I forgot to let me edit this I'm going to call this YouTube coffee server version too there you go so now I have that and I can easily connect and we can check that out um okay so we have that so it's it's working perfect so now let's move on to um the creation of our migrations now something that I also do is I like to put the start containers so whenever we have this you know in development and we already created our container and our TV inside of our container we can easily start the container with just a star container command so actually start container not containers uh this is very easy we're going to do Docker start and I'm going to pass a DB dark container very simple so I'm just going to show you I'm going to stop this um and then I'm just gonna run make start container and there you go it's up and running again so it's something useful to have now we're going to go ahead and do create we're gonna create our migrations create migrations and I'm going to be using sqlx um not great and r in it I'm going to show you guys what sqlx is so sqlx SQL X CLI so there's two ways of installing um SQL xcli for people that have Mac OS just do Brewing style SQL xceline is actually very easy to install this way in the keys that you have Windows or Linux I think you can use home brewing Linux but it may be a little bit tougher to do the the other thing that you can do is install rust with cargo and then you you can install um sqlx CLI with the cardboard tool management normally I don't like to rely in you know other language related tools but I believe that in this particular case SQL X is actually really really good so that's why I'm going to be using the SQL xcla and this is how we create our migrations uh initially so I'm going to do make create migrations as you can see this created a file within our coffee server folder two files the op file and the down file so the app as you can guess is gonna you know upload the migrations it down is going to revert whichever migrations we make so now that we are in that topic let's let's make sure that we um you know I have the proper code to you know create tables and whatnot and by the way I'm going to be putting this on GitHub that way you don't have to uh write it by hand and not because it's hard but because sometimes you have typos and it can get a little bit annoying if you don't have like the exact uh wording or or the exact code and whatnot so I'm gonna be putting these on GitHub so we're going to be creating the following um we're going to be using uuid so this is going to be an this a function that creates um uuids and it's just way nicer for uh posters to deal that you could create it manually uh within your Golan code but it's just easier for uh postgres to deal with that so that's why I have it uh set up this way so we're sorry so we're gonna set it up like that and on the down file we're going to do the following we're going to say whenever we want to um you know refer any migrations there you go not here here there you go let's put that code okay so we're gonna we're gonna be doing the following drop table if excess and we make a reference to the table okay so now on the make file um so let's go ahead and create our migrations so we already have the um well we created the migrations folder I want to add the migrations so let me just uh reference my notes okay so let's start with the uh uh migration the op migration so I'm going to do my grade up and he's going to be the following uh the the code sqlx migrate run database URL and we're going to be doing the following um and we we could probably put these on the wmb so it is a little bit easier to um you know write but for now I'm gonna write it this way if I see later later that it's more useful to put everything within the dot EMV I'll do it uh but this allows to make it easier to change the user password and whatnot so we're going to do postgres [Music] semicolon slash slash user sorry calling password then we're gonna put the host so a host there you go then we're going to be declaring the database port the database name and lastly if we're going to be using SSL mode which currently I have it disabled so I'm going to put this simple okay so let's go ahead and test that code so for this I just need to make sure that this is connected and I have no tables so now I'm going to do make migrate up and felt user for root uh probably I have a typo here so I just want to make sure that I put on the let's open the dot EMV user root so all seems to be fine so maybe I have a typo here on my URL um postgres user yeah password I didn't see that so you probably caught this uh so if you caught this that's good um if not we can just run it again and there you go you see uh applied so now I'm gonna go here and we're gonna have um we should see interesting uh make my grade up database URL I'm gonna do my uh make my grid up again the possible one one reason why this is not um pulling this is maybe I did not save it it's not pulling the it's not creating the table it's because maybe I didn't save it and that that has happened before uh so let's see interesting table root public okay so I mixed I mixed this up wow okay so let's do the following this this is going in down and so maybe you also caught this um okay so that this is where the down code goes and let's delete that put that there okay now this should be working um so what's cool is that it has a uh what's probably the plan but has been modified okay so this is a good moment to revert the migration um because it says what's probably applied but it was modified meaning like you know the migration has a track of what we did and previously we had the drop code so we had that code in the in it up so now well it's a good time to add the um migrate down that way we can revert all right great that way we can revert our migrations so migrate run know migrate Rivers and we're going to be copy pasting the whole the whole line after the run on line three we're gonna put it here and we're going to be testing it so I'm going to do make migrate down and it was applied so now let's make my grade up and we should be able to see the table now and there you go we have the coffees table so now we can see that both the migrate op and the migrate down work perfectly and I guess that's a good example on when do we use my create help I migrate down whenever we mess up something whatever um that's the reason why we have the the ability to revert migrations also if you want to change them I mean you can alter tables rather than like you know reverting a whole migration and whatnot but you know it's there if we want to use it so now now that we have that I know that we have no golden code um whatsoever at this point and uh we're gonna start doing that now so I'm gonna be doing the following I'm going to create a command folder and within that command I'm also going to create a server folder so that is very standard within a golden application and that's because you can have um you can have a full stack application kind of like Django you can have a API also like we're going to be doing right now and you can have a CLI application within the same project so you divide them uh using this folder standard convention you know this naming convention so that's why you see this command server naming convention so anyway within the server is where we're going to be putting our main file or like the entry point or the execution point of our API so this is going to be our main package and for now I'm going to just be put in Fox Main and FP API is rotten obviously um don't forget to import fmt or the form of package and obviously this is not a server running this there's just like a print um statement but for now we're going to live like that so um a couple of things that I won't turn into the make file and I know that this is very thorough but this is going to be a really you know a good helping hand when we start developing our API the fact that we have a really good make file will help us in the long run so the first thing that I'm going to do is I'm going to use a build and again I'm going to be doing the following I want to um this is really not necessary you can do it manually uh same for the start containers the stock containers are commands that are nice to have you don't have to put them but I think they're really useful because you can just execute it and the make file will check for you whether a container is running whether if if the container is not running Etc same with this when we start a build process what I'm going to be doing right now is to check if there's already a binary file existing so if the binary file already exists then it's not going to create that binary because we already have it um sorry it's going to check if the binary exists so if it exists then it's going to delete it all right so we're going to be doing remove binary and we're going to Echo that so we put Deleted and the name of our binary but if the binary doesn't exist uh a code leading let's indent this okay there you go but if there's no binary um already existing then we are going to create a new one so no do I want to put that I could build a binary I think I'm I think I'm gonna and uh um if statement there we don't need an else to be honest because I had previously an if if else but with the with just the is more than enough I will put however the echo of building binary and probably I have these else when I was developing and testing this command but since I've used this before I know that this works so I'm not I don't need to use anything else uh bash script so I'm gonna build the binary and I'm going to put that in our server I mean and I'm going to be compiling this from our Command server uh main.go file because we're only going to have one main file but I've seen people put in everything within the server folder so you can just put the star.goal declaration and it will compile all the gold files that are needed to run the application when we run we want to make sure that we build a new binary so when I put this command next to the run it will essentially first run this command then it will run whatever we put underneath this uh command so we're going to put start in uh actually I don't want to put starting binary build because that's already done I do want to once the binary is built I want to execute my binary and put Echo API started okay uh we also want to put a stop command that's uh you know in case we want to run this in the background uh when we want to be able to stop it um so we're going to be doing the following Echo stopping back end and we're going to be doing the following P kill sick term and we're going to be pointing to our file which is uh the name of whatever we called our binary then we can you know signal again uh a server stopped and I'm gonna put stop in server okay perfect so let's go ahead and test our let me close this let's go ahead and test the build to make build and we have a syntax probably I'm missing this if then okay that's fine am I missing if I okay and there you go so our coffee API is created now I'm gonna run again make build and you you probably will see how it it gets deleted and then built again so you I don't know if you saw that like quick flash but that's how you can tell that it was um you know delete it and then build again so now I'm gonna do uh run sorry make run and make run um you know runs the by the the command build which deletes and creates the binary again and then as you can see here um you see API is running which is coming from from our main.go and you can also see the API started I don't know if I want to put API started um I don't know um that shouldn't be printed there you go so API is running perfect I don't know where I put that um okay so it's working and make run build run yeah I I believe that's what we need uh I have another extra um command which is a start but essentially is repeating the wrong one so there's no need to to create another command that's all we need Okay so let's start in our um let's start with the go Application I know we took our time but believe me this is a really good and solid base to start with um so now that we have everything that we need within our um make file what we're going to be doing now is uh make sure that we can start the server and by that is creating an actual server that listens or opens its port to whichever clients request um the the server data connection replies and whatnot so let's let's start that so over here what I'm going to do is the following I'm going to create two structs so I'm going to create the config structs and I'm going to create the application struct now let's start with the config strand so I'm going to be putting a port of type string and in the application struct I'm going to put the config of type config why do I do this because right now we're not going to be doing the addition so here normally I put models but we haven't created any models yet uh you know in this case the coffee model or entity that we will be using but later we're going to be putting this so it's really easy to do um you know extension methods and getting the properties of the application especially when you have more models you can just add more and more oh actually they're called fields in Golden you can add more and more Fields inside of the application instruct uh again for now we're only going to be having config so it might seem a little bit redundant but trust me it's it's a really good way of organizing your your application in this in this way um so I'm gonna I'm gonna be doing the following I'm going to add a method to the application struct and we're going to be doing it in in this way so we're going to be adding the method uh pointing to our to to the struct so our method will be the surf method which in return will only return an error if there's an error then you know you return the error otherwise you just return the a nil error now because serve is will be a continuous listening uh process you will never return until you you quit the application when you quit it'll return nil or if if there's an error it'll return the error um so yeah the first thing that we are going to be doing is loading our wmb variables so I'm going to be using go dot so go.emv.load and obviously we don't have this installed but I'm going to be doing an import and I'm going to write it here and later I'll show you a very neat trick that I really like but we're going to be doing the following GitHub github.com and this is going to be coming from joho got go dot EMV and as you can see my goal and Survey is telling me we cannot import we can find it on our on in any package so what are we missing here so we just we only have one file and if we want to start adding packages and whatnot before I do the the importing or downloading of the god.dmv file we need to create our um our module uh or goaling module so what we're going to be doing is um you know precisely that create our golden module which we're going to be doing in the following way uh go mod init and uh so actually I'm going to be doing this and you'll see what Golan says it says like okay if you're going to initialize a module uh put a name you can do example.com blah blah so we're going to be doing the following go mod in it I'm going to put um GitHub it's very customary to use your username kind of like you see um here uh right so this person is doing the same the GitHub their username and the name of the project so I'm going to be doing something similar so Artur feel and I'm going to put YouTube coffee server YouTube I'm gonna put YouTube go coffee server there you go so now uh you should be able to see that go.mod and we don't have any packages or I guess dependencies you can call them so I'm going to be doing the following I'm going to do go mod tidy and what that does is that if it sees a an import here but it doesn't have the import in the go mod it's going to add it so now we have it so that's that's what I think it's uh you know really cool from go okay so now that we have that we can do go Dot go.emb.load uh we want to make sure that we are taking an account you know situations where the EMB file is not loaded properly so we're going to be doing if earn does not equal nil and I want to obviously assign this to error so error equals to go.emv.load so if something goes wrong we're gonna put uh fatal and uh message this to whoever is trying to load to you know to us or load in wmb file otherwise we just continue with what we were going to do and I know it's just like four annoying lines but it's it's useful and easy to see when you are not loading properly your wmb file and you know you save yourself a couple of minutes from figuring out why sometimes your application is not working so that's why we need to put that so once that we have our uh dot EMB file loaded we're going to get our Port value in the following way we need to import the OS package so let me there you go the luck could not import I wouldn't worry much about this uh yeah there you go so I just need to I just have to save it okay so porn we're gonna you know add the port to that uh so now actually what do I have a print line so I'm gonna delete this and I'm gonna put it here so API is listening on Port and then I'll pass on the port variable okay and lastly I'm going to declare a server variable which will be pointing to the HTTP Library server struct server there you go and within the server struct that the HTTP Library provides we need to pass an address now I know some people only think why do you do it like this and not just you know create the string but apparently if you don't write it in this way you get multiple errors so you know I just write it with a format spring def and then oh okay so we don't have a router yet so I'm actually going to delete this line and put a to do add router so we're gonna have to do that later uh but for now it's fine lastly we're going to return the serve the server and then just put or more than put execute the listen and serve method now so that is our surf method we want to also add everything that we need inside of our main function so because we we cannot um I was before this tutorial I was actually adding the port as a global variable but since you need to go dot dot load function or I don't know if you can do it globally but for now I have it declared you know twice here uh maybe a general function would be ideal but I don't want to start experimenting uh you know in this tutorial so I'm just gonna leave it like that so we're just going to be repeating the the loading of our DOT EMB and then we can go ahead and create a config struct where in our config we're going to declare the port which will equal the OS dot get EMV port so now that we have that we are also going to get our DSN DSN is just a string um actually that is to connect to the database I'm not going to do the connection to the database just yet we need to do a couple of things before we get to that um so I'm just going to leave that out well I'm just going to leave that as uh to do connection to DB just so I don't forget and then we are going to create our application construct here so application and I want to be referencing the memory address so hence the ampersand and I'm going to do config equal to config and the models as before I don't have them at model later I can put here at to do also okay uh which currently we don't have this field but later we will add that field and then lastly we're going to do app well error equal to app.serve and then if the error is not equal to Neil means that we have an error and we want to log it well F no just fatal okay and we'll pass the error there so that is all we need to have our server running so now what we can do is go ahead and do the make run so now everything is automated and as you can see it says API listening on Port 8080. that is perfect it's working perfectly and um you know our service listen import 8080 uh let me see if we can actually test this so localhost 8080 and the fact that we see a 404 means that something is actually working um otherwise we would say like no connection or whatever so that's a good sign obviously we don't have any routes or whatever setup yet so um you know that's why we don't show anything but um yeah the fact that we see that is a good sign okay so we added our um our server creation um let's see what else do we want to do because I want to go this in order I want to do this in order sorry okay so what we're going to be doing next is connecting to the database um so let's do the following we are going to create a folder called DB so let's go inside of it well actually within the coffee server level I'm going to create my DB folder and there I'm going to create my db.go um file so we're going to be doing the following um I'm going to create another struct so type DB shocked where it's going to be called DB and this is going to be pointing to the SQL DB probably a struct and we're going to be using this Library which comes by default I'm going to be also declaring the database connection and that will equal to the memory address of our DB struct I'm also going to be creating three variables here three Global variables these are going to be constants So Max open DB connections this will be 10 Max connections um the max idle time which will be fine or sorry Max idle DB connection sorry that will be five and the max DB lifetime maxdb lifetime and we're going to put five times time Dot minute and my stupid lifetime okay I believe we should be good with that so now and you're gonna see how this um relates to the following function uh we're going to create a function called connect postgres I could be connect postgres DB connect postgres whatever but I'm going to leave it as connect uh postgres and we're going to return a pointer to the DV and an error obviously uh if all goes well the error part will be nil I'm also going to clear a d which will reference that database so that the variable yeah that t variable will reference the the database connection and we're going to be using a PGX driver and we're gonna have to pass the DSN which is the connection you know the local holes the user the password the port and whatnot that's what the DSN refers to and you'll see how how we will be using the DSN right now so if there's an error uh we will return a nil pointer and the actual error otherwise we just go ahead and set that database connection of uh said Max open connections equal to Max open DB connections d Set Max Auto connections equal to Max idle TV connections and these Set uh what was it Max life Max lifetime equals to Max DB Lifetime right so we're just referencing these variables here in here and not rather than just put in 10 5 and 5. this is just a nicer way to create the well to send rather the properties of our database connection because here you can change it and then your code doesn't break so it's just a nice way of doing it um you could all possibly also just pass the numbers here but you know I think it's a it's a good practice to to set up your variables and then you just change whatever is above and you don't mess with the with the inner code of the function so uh here I'm going to make sure that we can test the DB and you know I'm gonna pass the DB driver setup we don't have that function so let's go ahead and create create the test DB method where this method will get the pointer uh to the SQL DB Library actually no not Library sorry we're going to be passing our DB connection setup uh my mistake and we will be returning an error so if all goes well that error will be nil otherwise uh we do print that error so we're going to Ping the database and uh you know same thing if it's not new format print the error and we'll also want to return the error [Music] otherwise we want to so format print there you go we want to make sure that whoever is running the server so paying database successfully and we want to put that message then we just returned a nil pointer so then we can continue with the connection uh connect postgres method so we have that same thing Affair does not equal new return nail error otherwise the dbconnection.db will set that equal to our D setup and we will return the DB connection with the nil error and there you go so that is our DB connection setup and now we can go ahead and go into our main file and you know here where I had the DB connection we're going to do that right now so um for that what we need is the following we need to get the DSN so again the DSN just to remind you I'm going to open the DMV okay I don't have the DSN uh okay let's write that it's just I'm gonna copy paste it um you can also copy paste it from the GitHub repo um I'm gonna put it on the description so that way you don't have any errors okay there you go DSN so again we just put the whole stick with the locals Point equal to 5432 the user the password the name of the TV now very careful here this is uh my other project the one that I'm referencing so it's not this it's actually uh YouTube coffee TV it's so more disabled time zone equal to UDC and connect timeout equal to five okay perfect so we're gonna go back to our main file and we're going to continue with the DB connection setup so the DSN now we can get this from our 30mb so there's the DSN variable and we're going to assign it the DB connection to our DB and this is not imported let's see this should import automatically let me try one more time uh TP okay so I'm gonna have to import it manually you probably won't have a problem uh for now uh since I'm using them it'll complain a little bit uh let me go to the go mod what did I put YouTube so I'm just going to copy this go to the main paste okay and get rid of this extra semicolon save and I'm gonna go down and where did I have that okay here so let's see DB Dot connect post press clear oh um one thing that I'm missing um this should have slash DB I believe I can initialize with value connect postgres TSN probably I need to get rid of this DB interesting um probably I didn't put out no I am returning to Paris um let me close this sometimes uh Vim takes a bit to process uh I'm actually going to delete this too just to see if it automatically Imports the DB package so DB no okay server okay it's not um importing that so GitHub .com I'm actually going to copy this from goldmod okay so let's go to the main um DB DSN and then let's see if it kind of goes to the all right that's that's strange but let's continue probably you don't have this on vs code all right so now it's pulling up the um the method Okay cool so it's working now okay so we have the DB connection there so now we want to make sure that we don't get an error and again we want to lock that so lock that fatal and if something what goes wrong we are going to put cannot uh connect to database we are also going to defer so defer again if you don't recall um actually so I have a YouTube series on um basics of growling and I teach you there what does the fair panic and I'm missing the other the other keyword um but essentially different specifically the fair I explain how the fair works which is like the keyword that allows the pros to run and then at last it runs whatever line you have on that day here and it's really useful especially with the DB connections where uh you want to be able to execute everything that you have uh for the DB connection then once you have all that executed then you can defer to the DB Connection close as we're going to be doing here so very useful using that to Fair okay so once that we have that then we have the application declaration perfect then we have all this the models we don't have them created yet so now let's go ahead and I don't know why I always open a new one let's go ahead and make sure that this runs I'm gonna do make run and okay so we have an error that's fine and it says cannot connect to database so at least it's good that we know where we have our error so let me see if I have an area in the DSN so I have to go into my 30mv here DSN maybe I forgot to write it okay no so it's not that I'm doing a YouTube coffee DB Okay so I don't think I have any typos there um make sure let's make sure the container is running okay the container is running so then we must have a typo in our DB uh connection file so I'm going to get my notes on I just want to double check that everything is in order so D and error equal to SQL open oh of course uh the Imports very important um we need a couple more Imports that I did not add so again uh if you don't add this you're gonna encounter the same error that I have right here you're gonna see the era of connection so we're gonna add that and the jaxi PG connection is a very useful Library so I'm just going to paste this three times and I'll change the terminations and then lastly uh this one is going to be live slash PQ okay so this one rather than PG con is going to be PGX version 4. and this is going to be STD lib so now um again I keep an opening a new uh that's fine again I'm gonna do go mod tidy which will go and fetch those patches for me uh uh STD leaves okay so probably I have a typo there is the jaxy PGX okay so I'm missing the PGX okay so now I'm gonna go again and do go more tidy perfect [Music] uh can I import okay so I wouldn't I'm actually going to do a right quit then open again the DB dot go I'm going to ignore this for now because um this should be installed and then if you want to double check you can go to the go dot mod and see the installation so yep we have everything there so sometimes again them can be like that uh if you're using vs code you probably won't have any problem and there you go so it says ping database successfully so that's great um so far we're doing great let me see how long it's been okay one hour okay so it's not you know we have a good time um you know we're under good time uh recording this so that's good and the connection to the database is successful so that is that is good we can continue to creating our entities and the you know crowd for the entities in this case this will be the coffee we won't have more uh not in this tutorial but normally you have for example you have the users you have whatever product you have you you can have categories you can have orders and whatnot so you can have multiple entities in your application again in this case we're only going to be doing the coffee entities so let's go ahead and create the those entities or rather the coffee entity and the controllers the you know any helpers that we need the router and whatnot so let's go ahead and do that so the first thing I'm going to do is create the services folder also so I don't forget I'm going to create the controllers folder Services also we're going to create the helpers folder uh helper Services controllers what else am I missing and the router router okay perfect so we have all those folders and those will be all the folders that we will be needing we will need to create any more folders so now um copy entries okay let's see um yeah we're going to start with the with the services looking I might not so um because I have like the guideline probably I wrote something funky there that now I don't understand but all good in general it's all outlined so let's start with the with the services uh so here I'm going to create a coffee.go file this will be under the package services and we are going to create our uh coffee struct so this is going to have an ID of type string and this is in order to um declare how we're going to be looking at the information when we send it via Json format so that's why we declare it in the following way and we're actually going to put it like that same with the name so again Json string same with the type of roast I don't know why I put string here uh this has to have a name then this has roast there you go an image uh same thing of type string region also type string region uh price here I'm going to put a float32 because we only have a 64 and a 32. and for this particular case uh 32-bit um field will be more than enough and here I'm missing the semicolon which uh you know the goal um LSB is nice enough to let me know I'm missing the columns there okay uh grind unit so how fine do I want to grind my coffee whenever I create delicious espresso so there's going to be a grind unit and I'm going to separate it with the underscore and lastly we have the uh you know management type of field [Music] created at and updated it so created that time dot time Json created at and I'm just gonna copy that and put updated and and here same thing the ad and and I don't think I want this weird time Library I want the normal time Library there you go so now we've created our coffee shocked uh we're going to start creating the get all coffees method so again we're going to be pointing to our coffee struct and to clear the name get all coffees now we're going to be returning a slice of coffee stocks and also an error so here on the return declaration I'm gonna put those two things so again a pointer we're going to return a slice of pointers and an error uh we're also going to declare our context and the cancel variable so here we're going to be writing context with timeouts context with timeout I'm gonna be passing the context and what what no no okay my mistake let's get rid of that so uh let's put contacts okay so it is with timeout and we're gonna pass the contest background and the DB timeout TP time out okay so now um this DB timeout actually we need to pull it from another file um currently I don't have that created so before we continue with the get all coffees method um which here again we're gonna have the connection to the database and you know we're going to be retrieving all the entries I'm gonna go ahead and create the main Docker file within our services so package services and here I'm going to create the constant DB timeout I forgot let me get the notes uh constantly timeout okay so the DB timeout will equal to three seconds so time second times three I'm also going to be adding this um variable DB and there's going to be a pointer um I'm sorry this is going to be a type of pointer uh a type of pointer of the SQL DB struct there you go so now here um the way I did this and you can think of this kind of like the index.tx or sorry index.ts or the index.js there's going to be our index file where we're going to be exporting all our models for our application to to consume that data so that is why I created a separate um main.co file so very similar to the application struct here I'm going to declare my model struct and I'm going to add the fields of all the models that we are going to have in this application in this particular application we're only going to have uh one main model which is the coffee model or the coffee entity but we're also going to have the Json response the Json response model now currently we don't have that so just to get that out of the way um I'm gonna write it here so there's going to be responses actually response.goal here I'm going to declare the package Services also and this is going to be a very short file I'm just going to write the type uh the stock type which again is going to be Json response and here we're going to have three things we're gonna have an error field so again there's going to be displayed as so when we pass the Json data the message field which again we're gonna write it like so and the data itself which is going to be of type interface which in this case is kind of any um you know the any uh variable in JavaScript and normally I don't like to put any or in this case the interfacing golang but uh because of the fact that the data can be um can be coming in any type of structure that's why in this particular case it's good to have a as it is all right so we have that we have the main uh file I I may have someone okay yeah I'm also going to create a function that will create a pool of connections so there's going to be fog new it's gonna get a pool of connections and then return uh the model connections so you'll see DB equal to DB pool which again is just assigning the pool to this DB pointer and then it will return the models uh struct Ure too many return values oh yeah I need to put here models there you go okay so we have that now we're good to go and continue with our coffee method okay so this is going to be the get all coffees obviously we don't have any coffees in the database so for now this method is not going to work so it is one we're going to declare and create this method and the create coffees method that way we can see how these two work uh in tandem so again defer cancel we want to cancel the connection once everything is done so I'm gonna be doing the following this is going to be a select statement and we're going to be doing the following we're going to be putting every single field of the struct in the query and it has a reason why this is done like so so name image okay ID name image roast and it doesn't matter that I mix them it's totally fine if I have here Rose uh before and then here I have image before it doesn't matter in this in this case region prize grind unit created at and updated at and this is going to be coming from the coffees table it takes the clan but not use create declare but not use okay that's fine now we're going to be doing the following we are going to be putting the um the rows right so we're going to be getting rows of you know whatever the database responses with or replies with sorry uh DB query context and we're going to be passing the database context or the state because that that's precisely what the context is is the state of the database and we're going to pass a query error but not use okay that's fine uh we want to make sure that we don't get any errors so you know your typical handling error code excerpt there you go I'm gonna get rid of that so we have more space and we're going to be doing the following I'm going to create a slice of pointers uh so this is going to be coffees and the the pointers type will be of type coffee so this slices this slice will be having multiple coffee pointers and what we're going to do is for every row so rows dot next that we have from our reply we're going to create a coffee bar coffee we're going to create a coffee struct upon that row and append it to our coffee slice so we're going to be scanning each rows each row uh field so this is going to be the first one coffee dot ID so I'm going to copy paste this one two three four five six seven eight and I'm gonna put the different fields so we have ID we have name we have image we have roast we have a region we have price actually I'm missing a couple but that's fine or one more uh we have grind unit and then we have there created that created add and updated ad so created that and updated app okay very declare but not use that's fine and this is important that all these decorations uh follow this order because that's in the order the order that we are going to be getting our rows so just have that in mind that this exact order should follow this order or vice versa this order follows the the order of the query so now that we have that again we're going to be doing some error handling making sure that we don't get an error if we'll get an error we want to return that error otherwise uh we want to um update that slice you know passing the the old state of the or the old slice right and the new value that we want to append which in this case is the coffee right here and we do want to pass the the pointer because again this is a slot a slice of coffee pointers hence why we uh you know pass the the address to to that struct which you know um later if you're interested when we use pointers it's just uh cheaper to pass a memory address rather than the whole struct and the application is faster but um I'm gonna make that video I think I have it in Spanish currently but I'll make that video in English so um you guys can have that anyway continuing this with this method I'm going to be returning the slice of pointers which is the coffees and nil error and with that we should be fine so now we're gonna go ahead and continue with the create method so again this is going to be a method which we declared in in this way so we point towards the coffee struct and that's how we know this a method now the name of the method would be will be create coffee and actually let me do that there you go and we're going to be using uh the following we're going to need a coffee um you know data or body or whatever we need to get that from somewhere so we're going to clear um that value or parameter or argument in this way and once we create that we're going to return the coffee pointer and an error so let's go ahead with the creation again we want to create error we want to get the context of the database so context with timeout and we want to get that context Dot background and also we won the context you know also using the DB timeout we're going to be using the defer cancel and now we can go ahead and create our query to create the coffee so to create the coffee we're going to be using an insert so insert into the table coffees with name image region Rose prize grind you in it created that and updated app and the values are going to be one two three four five six seven eight so one two three four five six seven it and we will be returning the whole the whole row when we create that coffee that's that's what the return star um refers to so now what we're going to do is assign just here we do need the two values but we really don't care for uh you know the the return um I believe I can put the response here um but if we don't use it it'll complain so actually I'll put response there and we'll see what happens but I'm I may be experimenting a little bit too much so I'm just going to put here uh I'm gonna put check so if there's an error I know where to where to go to the check but if not I'll fix it and put it as I have it on my notes so anyway I'm gonna put an exec command so we're going to execute our query uh we're gonna pass a query and also we're going to pass um the fields that we get from from the parameter of this function right where this coffee is is the one that we'll get here so again this has to be in the same order um as the order that we have in the query so coffee dot name and I'm going to put eight more times one two three four three five six seven eight maybe yeah that's fine so name image region roast price grind unit um created at update that and do I have one extra one two three four five six seven eight oh I have an extra and by the way rather than doing this the created and updated that we're not actually not going to get it from the uh coffee dot body from the coffee body that we get we're actually going to do time dot now so we're going to be handling that internally and that's a common thing so that's how we're going to get the created that and updated that field same thing if there's never we want to return the error otherwise we return the response and the Neil that's the reason why I didn't do that okay because this return is probably an SQL formatted and probably we need to do more manipulation um so I'm just going to put another score here and then instead of dot rest I'm just going to put the coffee now mind you this is not the coffee that will be stored in the database there's just the information that we use to create the coffee but if all goes well and we get to to this stage it means that everything went well and we saved our coffee with the information that we have here so it's totally fine that we leave this method as it is and actually now I don't need to check anything because I know that this the other way that I had it will give me an error well not error but will give me more unnecessary trouble Okay cool so we have that uh in place so now we can go ahead and start uh you know adding the controllers and in the routers we also need to add the helpers because for the controllers we need we need to be able to uh retrieve Json and also uh write some Json and whatnot so we're gonna we're going to also create helpers um so let's see okay all right so let's go ahead and create the helper methods so this is going to be a file called helpers.go so package helpers and here we're going to be writing the following uh we're going to be creating a write Json method or a rather than method function you read Json function and also a couple of variables that will help us with that so let's go ahead and do that um I don't recall using the envelope um this is a type of interface that um helps structure name response in such a way that it looks nicer but I'm gonna write it in case that I need to use it um so I'm gonna put that there again we're using the empty interface to allow us to have you know any type of response slash envelope specifically when we use Json responses so hence uh the interface type there envelope with an e at the end okay we're also going to have a struct um of type message where it's going to have two Fields the info log and this is going to be having a this is going to be a type of pointer to the logger and then error log which will also have a pointer to to the lower struct obviously as you can defer one will lock just information the other one will log errors uh we are also going to declare two Global variables that will extend uh the info log and error log fields in the message struct so info log equals to log that new always.std out and we're going to prepend uh the log the info log message with info and we're going to pass the uh date to the logger and the time so L time to the logger we're going to be doing something very similar to the error log so there's going to be error log now same thing again where the nympho there's going to be error and also we're going to pass a log date and a log time but additionally we're going to pass an L file which is log l Shard file log l short file and this because if we have an error we want to know um which file is the one that is having an error so now uh what we're going to do is also create this Global message logs struct so message logs strong which is going to be created upon the message shocked that we just declare above and the full info log field will be assigned to info log and the airlock field will be assigned to our error lock there you go so now uh what we're going to do is create the read Json method which will use the response response and request so http dot response writer and dr4 request so http.request and um we also need to get whatever data we are receiving right because if we're reading Json if we're reading data or rather reading Json uh we need to pass that in the parameter in the parameters um so what we're going to do is declare a max amount of bytes that we can read and this this is going to be in Json so I'm not a hundred percent sure but I'm 95 sure uh that this is actually a standard of of data that you can run in string because again Json is just a string formatted uh in in Json uh fashion hence uh in JavaScript fashion hence the Json which is Javascript object notation but in reality it's just a string so this should be more than enough to get any top of string so 10 4 8 5 7 6. and then the request dot body is going to be assigned or then assigned we're going to set that uh Max byte so max bytes reader to the max to the max bytes I should put here Max bytes there you go so we don't get that Max by uh okay yeah that's fine now we're going to put the decode as DEC Json dot a new decoder so we're going to decode whatever we get from the request dot body error if there's an error when we decode that so we're going to try to decode the data that we get again if we're going to mirror we want to return it and we also want to make sure not only when we decode it but when we uh shocked if io.nf file returned only single Json okay so in case that we see like two um really this is just a safe keeping but making sure that when we parse the Json we don't have like two um two objects so we're just saying um you know if we see two open and closing brackets of adjacent then obviously there's an error there so if the error is not nil in this particular case we know knew that there's two Json objects which that is not right normally you just have one main object and within that main object then you can have attributes of that main object so we're gonna put um body must have only a single Json object so again this is just uh safe housekeeping us or safe keeping I forgot the proper phrase but anyway it's just like um you know managing reading Json which you know is important so we have to read Json let's go ahead and write the the right Json method so this is what we are going to be returning so HTTP dot response writer are you know making the HTTP dot risk Quest sorry and actually um I'm not going to need the request because the request is used in the read so rather than using that I'm gonna pass the status what I'm going to be returning which is you know of type enter empty interface um and also we're going to be passing whichever number of headers we need to pass so I'm going to declare a variable out an error and set that equal to the Marshall indent so Marshall um that's how you um you know convert into Json and I'm also going to tab um the data structure in that Json rating same thing and there's an error and the error equals is not equal to nil then we return the error also if the land of the headers is bigger than zero meaning if we are passing any headers we want to uh set those headers so for the key and value of each header we want to write the header with the key and the value I'm going to put wrench okay so now that we have that um we're going to do right header dot set content type and application Json okay we're also going to write a header and put this the status code and then uh right all the um all the data that we converted adjacent so if we have an error same thing we turn the error otherwise we return new and mix name and I'll name uh oh I'm missing the headers here naming headers okay expected operand found Len headers is equal to zero for header equals key value am I missing something [Music] probably I have a typo here but I cannot see it let's see well I don't have anything there Jesus wow I don't know how I missed that anyway there you go so that is our uh right Jason um and actually I'm missing one more uh method which is the error adjacent I guess that we could use the ride for this but since uh you know we have a very particular use case which is returning errors I guess it's good to um you know create a specific error Json method so the status code will be equal to the HTTP Dot status bat request e the Len of the status is bigger than zero then we'll set the status code equal to the first status code uh that we get the sorry the yeah from here and we are also going to declare a payload where we're going to uh assign or we're going to assign the type to the to the response that Json so serve this says dot Json response and I want to see what did I bring from service okay yeah uh we're going to obviously get distract from our package Services package and the payload dot error will be equal to true the payload Dot message will be equal to ER dot error and we are actually going to make use of our right.json to write uh the error and there you go those are our helper functions which we are going to heavily rely on so it's very important that we create this before we go into the controllers so now that we have that uh we're going to go ahead and create the controllers uh we only have right now one entity which is a coffee so we are only going to create One controller currently but um obviously if we would have more we would create more we don't really need uh main.go file in this case for the controller so we should be fine with that so let's go ahead and start with the cad coffees okay so in order to make this um a little bit simpler I'm gonna be doing the following um I'm going to be declaring actually I wanna I'm gonna put this here okay so coffee will be a variable that will contain the uh coffee strong type and what we're going to do is make use of this coffee variable for methods and whatnot you'll see right now so we're also going to call this get all coffees uh we're gonna be having the resp uh response writer our http.request and we're not going to be returning anything uh not in not in this method uh at least we're going to write Json data but you know the Json data will do its thing we're not returning anything uh in this method so we're going to declare all as all coffees and the error and we're going to do coffee Dot get all coffees and also uh do some error handling so if we get some errors we need to log that message and we're going to be doing let's just log rather than info lock fatal we're gonna do messages error log and then we're going to be using the print line and I know this can be a little bit wordful but uh it's the only way that we can append the you know the error with the indentation and the file there's an error and all that good stuff that our struct gives us so we're gonna have to rely on this and we're going to return if all goes well then we're just going to write the Json with all the coffees that we get from the database get or rather than get return HTTP status okay and with the envelope we are going to return the coffees as so missing Keen map literal let me see probably mastering interface uh map shrink time envelope uh what was the controllers oh it's not a comma it's uh semicolon okay my mistake there you go so we have to get coffees now let's also go ahead and do the create coffee uh controller so same thing this is going to have the HTTP response writer and the request pointer so HTTP dot request and we're gonna be um let me put here the post coffees coffee here we're gonna put um or rather than put declare the coffee data that we get from the from the request um and this is going to be of type coffee we are going to set that decoding to an error in case that there is so we're gonna grab the the request body and decode it and put it into our coffee data if something goes wrong again we need to handle that so we're going to do helpers dot uh message logs dot error log and then dot print line I know it's a lot but again it's helpful in that way and then we return the error actually we don't need to return it we just printed otherwise if everything goes right then we write the Json with the newly created coffee so status okay and we passed the coffee data um uh now the coffee created will be equal to right now we haven't done anything uh we which actually to be honest um I'm gonna I'm gonna put here check we should we should put the writing after it the copy is created um but I'll see right now if if you know everything goes well anyway so first we need to create the coffee we want to make sure that that is created before we write it into the Json so coffee uh great coffee and I'm gonna put the coffee data right because we're going to be passing gonna use coffee cream coffee value um [Music] coffee Services uh coffee data oh um yeah here I don't know why I did it it should be coffee created ah there you go so now uh what I'm going to do is if there's nowhere well first to if error does not equal to nil we're going to put uh helpers Dot message logs errorlog dot print line error and then uh and then return otherwise I'm going to do um helpers dot right Json HTTP dot status okay and then pass the coffee created so this should be um there should be enough um I just want to see if there's no errors because I did it a little bit differently from what I have it on my notes but I think it should be fine if not all I'll write in as I have it on my notes but so we have the controllers created now the last thing that we need to do is create our router in order to see this in action so let's go ahead and create the router so we're going to declare the package router and for the router we are going to do the following so we're going to declare a routes function so this function will create and return the routes and this is going to return a type of HTTP Handler so it's going to be returning that type of struct so my router I'm going to create it with Chi because that's the router that I normally use and I think it's a really good router it's a router that mostly use the standard Library so in case that you want to change it later it's actually really easy to do so um So currently I don't have this installed I can do later uh you know I can do go mod tidy so so well I can you know I already wrote it so oh my tiny uh probably I need to save it there you go so now it it installed the Q router which actually um finally found uh yeah actually we're going to be using the version five anyway I'll I'll deal with the Imports right now but first let's uh let's do this and it says on the clear name g that error should go away so I wouldn't worry about that yet we're going to do router.use and we're going to be using a recover so recover which also comes from Chi uh it's not from okay so this is not from Fiverr actually uh this should come from the QI Library uh there you go Chi G B5 should be middleware okay um we are also going to be using the course so router dot use course dot Handler and we're going to be passing the course options um we'll put that there now I'm gonna put again my GitHub uh repo so you guys don't have to like write this it's really not worth writing this uh by hand you can just copy paste it um it really doesn't like add any value for you writing this specifically or obviously everything else is um valuable to write on your own but this particular case the you know the course options not really obviously it is important for you guys to know what are you writing but if you copy paste it it's fine so I'm gonna put that there again so the allowed Origins the loud methods allowed headers um the expose headers to allowed credentials and the Max stage of the of the course all right so now that we have that we can go ahead and declare our first routes so I'm going to create my get route to get all the coffees so there's going to be API slash V1 coffees and you may ask yourself what is the reasoning behind the V1 the thing is that you can have an API and you change it and it completely changes the way you return information but let's say that you have clients that rely on your API or you have applications that rely on your API multiple applications like mobile tab stuff whatever so what you do is in order for everyone everybody to do a smooth transition you leave the API version one working and then you release a version two so then people can do the smooth transition and you know you have both working at the same time then once everybody does a transition then you can get rid of the version one API methods and that's that is the reasoning why you put API V1 uh you don't really need it you don't have to put it if you don't like it I just like to do it uh but again it's you know not really necessary it's actually more for people that only provide provide apis to uh you know third parties in this case uh this use case would be more for just our server and our internal front-end would be our client would be cons would be consuming this so it's not a big deal whether you put it or not um to create a coffee we're gonna do API slash V1 slash coffees slash coffee and I'm gonna pass the ID there's a lot of people that think that um this is redundant uh yeah I mean it really it's up to you let's let's do it this way let's get rid of the single coffee uh wording and I'm gonna pass the create coffee method and again we don't need to do the opening and closing and we can pass it kind of like as a as a callback right and the controller already has the the request and response writer um you know declared so we don't need to pass anything there and lastly we're going to return the router so we should be fine with that now I'm gonna do go mod tidy to make sure that we have the chi libraries installed uh I'm actually going to quit uh an uh any of them to see if we call okay so now we don't have those errors but we do have the recover this is actually recover error so probably you need to change this too uh where else do we have thinking controllers okay we don't have any errors anymore uh okay so we should be having everything good to go uh the last thing that we're missing is adding our routers and models in our main file because remember we had the in the main server file remember we had the to do things so here we're gonna go ahead and now um we're going to update this so this field is going to be named models of type models the clear name models and then we're just going to import the DB package and then clear name models that should be that should be working let me see if I did something different oh Services okay so sometimes 3M is not working with me so I'm just going to import this manually services oh oh that's why this is services.models there you go so we should have that in place so now it should be working properly now also here the to do um I'm gonna get rid of that on where we have to do I need to add my router here so this field is called um you know for the router it's called a Handler and we're going to be passing into our Handler our routes so we're going to say router dot routes because remember this router package is from from here from from here all right so we have that in place uh we have the listener server let me see if I have another to do okay so yeah we need to add the models there so I'm going to be doing in the config sorry in the application struct models right because we would change the struct but not the object that we created Upon Our struct so we're going to do services that new DB connection DB so this is going to create a connection um with the database to get the the models whenever we want to you know retrieve the coffees creating coffees uh update or delete so right now we don't have update delete or get by ID but we just want to test those two so I'm gonna go ahead and write that that change I'm gonna do make run I'm just going to write it Ron make sure that we don't have any errors okay that's perfect no errors so I'm going to open Postman and we're going to make sure that we can do the um get and post let me so by the way if the get is working we should see the following coffee snow that's great so it means that it is working but we just don't have any copies so here I actually pre-added the data we're going to put the name the region the rose the image the pricing the grain unit and the created data and updated ad will be created on its own um same with the ID um the URL is going to be localhost 8080 slash API slash V1 uh Slash coffees and actually I think I miswrote something uh this is not gonna work so yeah so um do I want to leave it like that yeah that's why I probably left it like that um so there's two School of thoughts you can either do the following yeah it's just that coffee and then you can put like create I'm just gonna leave like that actually so I like that way better so coffee slash coffee yeah so we're gonna have to rerun this so I'm going to re-execute our make run it'll delete the the binary uh create the new binary and run it again and we don't have any errors uh not that I can see at least just to make sure I'm gonna run the not this one this by get ID and we don't have this uh Disney testing it prior to the video all right so it works so now I'm gonna go back to the Post and I'm gonna write uh the following uh let's put uh it was not XO it was I don't know let's put uh Panther Coffee which is actually a really big coffee and we get the okay now we don't see anything here uh hopefully I don't have any error okay so now we do see uh syntax error at or near return now the problem here is that we have multiple uh multiple coffee files just to make sure that I didn't actually okay not this one all right so we didn't write anything uh um coffee dot gold so 35 all right so I believe it's not this one this should be fine it's probably I believe it's from the from the um controllers so controller's coffee 35 yep coffee created okay let me see if I have an error I'm gonna see my notes coffee dot go create coffee okay so let's see we have the barrel and the clearing we have the decoded information we have the error handling uh [Music] this okay so what we need to do is um I am not 100 sure if we need to I to me it doesn't make sense that we need to um decode and also write Json in order to pass it into the create method but let's see because I I did write this a little bit different so let's see if that is the culprit of our error dots status okay and I'm gonna pass the coffee.data again um let's see that's fine now let's exit okay so it seems like so um still it still says there's an error so um near the return there's a syntax error okay interesting so let's see I'm actually going to do the ghetto coffees to see if okay so it was not reading to the database okay um let's see apparently there's a syntax error somewhere here um Okay so error helpers message logs error log print line error return so so far I see everything is is working [Music] um in my opinion um this should not be happening so I'm gonna get rid of this um what else I want to do one more thing here second or check and then yeah this is like the famous console log so I'm gonna do make run oh I'm just gonna call my hair on both okay all right so I'm gonna rerun that we're gonna see the error again and so it's in the second uh check so it seems to be in the in the coffee data part okay this is so I've been checking the code um so you guys will have to like see me going through the code um it actually didn't take me that long in this case thankfully um but I found the the air it should say SQL error um returning and it was a little bit difficult because it says uh return so I was looking for a return but I should have I should have seen and I'm gonna show you guys um so it says SQL state so I should have known that with the SQL state it was an SQL related error and I should have I should have found that um uh faster uh thankfully it didn't take me that long but yeah that was the error I had returned rather than returning which is the keyword that we need um if you don't have that you're gonna get that error so again let's just make sure that um you know this is working so I don't have this method written yet this one sorry so we have kavi snow is working perfectly and then we're gonna post a new coffee and there you go we have the um well this ID um let me see what I'm returning and uh controller so the coffee created okay so I'm returning the coffee created uh yeah that's perfect and I'm gonna get rid of these console logs uh so even though we don't have the ID because the ID is generated at the time um this should be working out so if we make this request as you can see we'd see the the coffee with the actual uh UI uuid generated and the proper uh date for the created and updated ad so let's go ahead and create another one just to see the get method working also with other um with another coffee created so I'm gonna call this I don't know and I believe that is made in Italy uh again no image price that's 11 grinding unit I actually use five and there you go Lavazza medium no image Italy etc etc and here then we should see both the Panther Coffee and the Lavazza perfect so now we have our application working perfectly we have almost everything in place the last thing that we need to do is create the get by ID update and delete so we're going to go ahead and start with the services and create those methods so let's start with the get coffee by ID which is very similar to get all coffees it's just that we don't Loop through the rows we only get a single row so again this is an extension of the coffees uh struct so get coffee by ID um we're gonna get an ID as a parameter and we're going to be returning a coffee pointer and an error so again we gotta pass the context and then later we cancel the connection contacts with timeout we need to get the context background or the state of the DB with the timeout declaration that we did then we do the defer cancel and um then we create our query choose select then we do the same thing that we did here so actually I'm going to copy all of this uh go down here and paste it and let me put that there there you go the only difference is that I'm going to do from coffees and also at the where ID is equal to one so that is the only difference and I'm going to put that there so it looks nice then we can go ahead and create create our coffee struct that we're going to be returning and then we're going to get a single row so we're going to do DB dot query we're actually going to do query row context in this case so let's do query row context where we are going to be passing the context the query and the ID and then uh within the row we're going to be scanning and also I can copy this from the ghetto method above so I can do the following and get this from here so I'm going to copy that and I'm gonna go to the line well [Music] here sorry gone a little bit lost there but there you go so remember inside of the get coffee by ID where we're doing the scanning and let me intend this actually the other side there you go okay and we need to pass the oh no we don't need to pass Eddie because it's already there sorry there yeah okay uh so we're gonna scan that row into the the coffee variable that we just created make sure that we do our proper error handling so return Neo and error and then if all goes right then we do a return and the um memory memory address to the to the coffee we just created and we just create sorry that we just got found oh very important and also very important okay there you go so we have no more errors um before I go ahead and create the the controller methods I'm going to go ahead and also create the update and delete that way we don't need to come back to this file so let's go to let's go ahead and write that so foxy coffee updated coffee should be update not updated and let's put this a little bit higher so it's easier to see ID string body of type of coffee and we're going to be returning a coffee pointer and an error so again we are going to declare the context and the cancel clause context with timeout where you're gonna get the context background and pass a DB timeout we're going to cancel the connection later so we're going to do a defer cancel so now we're going to do the query and update coffees so we're gonna update the table and specifically a single row for that we need to set the name to the uh you know first value that we have the image the roast the price the grind unit the region and the updated ad we obviously not we don't need to update the Creator apps and that row is going to be updated where the ID is equal to whatever if value would pass and again returning uh everything so after that we created our or rather than create we execute our query where we pass the context the query body dot name and let me copy one two three four five six seven uh the ID we passed there so body dot image body dot roast body Dot price dot grind unit body dot region and the updated that we actually are going to be doing a time dot now because at that precise point in time was when it was updated and then the ID also again our proper error handling and return that if there's such error otherwise we return the body diet now again um we could do I could put the response here get it from the SQL parse it return it it's just too much uh work unnecessary work where if you get to this point it means that your process was done correctly and hence you can just return the body so that's why I rather have the code as it is and then lastly we're going to have the delete with which is actually really easy to do so coffee delete coffee ID string error again we need to declare the context and the cancel where this is uh context dot with timeout and we want to get the context from the background and we're also going to pass the timeout cancel the connection and then the query is very simple delete from coffees where ID is equal to one probably didn't need a back ticks but well there they are and then we execute the query and we pass the ID lastly make sure that there's no errors um turn the air otherwise we return nil so there you go that is all that we need for our services so now we're gonna go into the controllers so I'm actually going to put here the uh get coffees coffee and I'm gonna put here ID so Funk get coffee by ID W HTTP Dot response writer R HTTP dot request and let me check this out okay so the way that we're going to get the ID which is from the URL is going to be in the following way so g dot URL from so from the URL parameter and we're going to set it equal to whatever we get on the request and the parameter is going to be called ID so if we put this like I don't know Val then this would be in our URL but since its ID we're going to look like that now the coffee that we're going to be getting is going to be done in the following way uh coffee dot got a coffee by ID we pass the ID we do error handling as always and we want to make sure that if there's an error we get the error and we print it otherwise we return that Json so helpers dot write Json with the right prom that we declare HTTP dot status okay and the coffee that we got okay so now let's go ahead and create the update method so coffees coffee ID so this is Funk opt-in coffee whp dot response writer R which hdp dot request and same thing we need to get this with the g dot URL Dot param same thing the way we'll get the ID bar coffee is equal to I mean we declare it as of type coffee so what we're going to do first of all is get the values of the requested body so Json new decoder r.body uh we're gonna place that into our created coffee variable so coffee once we have that [Music] um we want to make sure that there's no error decoding this so if there's an error we want to know so HTTP dot error and we are going to put that inside of an error and um make sure that we display that it was a status band request and return otherwise we are going to go ahead and continue with our update of the coffee coffee updated so coffee dot update coffee we're going to pass the ID and our declared coffee okay now I know that you are seeing like hold on a second then this got um declared all the way at the top and it did but [Music] um actually we could even get rid of this since we already have it at you know above it should be fine actually uh just to not get like confusions I don't think there's anything wrong with that but let's do um coffee coffee data so this will get from services that way it's very clear that this is the the coffee data that we're trying to update very similar to The Creation method so coffee data there you go and now same thing we want to make sure that uh everything goes well so if the error is not equal to nil then we do a helper how helpers Dot message dot error log dot print line and then we put the error there otherwise then we do the helpers dot write Json TDP Dot status okay and we put uh we passed the coffee updated and lastly we'll do the delete method so coffees coffee and also pass the ID and this is also a very quick controller to create so delete coffee again whdp dot response writer r http.request we need to get the ID from the chi g dot URL param um again we want to make sure um well we're going straight into the deletion so coffee dot delete coffee we pass the ID we do our error handling http dot error so um actually I don't yeah there shouldn't be an HTTP um declaration this will be actually easier with do helpers Dot messages dot error log dot oh print line and then we'll pass the error there shouldn't be any error with this and then lastly follows well we do uh helpers dot write jsonride http.status okay and then rather than passing a strong we just do sucks successful deletion perfect so then the last thing that we're missing is adding those methods here so I'm actually going to copy that and here I'm going to put coffee slash ID here I'm just going to do get coffee by ID I'm going to do it here now the put coffees and pass Eddie again then this is going to be uh optic coffee and lastly this is going to be a delete method and I'm going to put delete coffee so just make sure that you have the methods correctly reading but those are methods I don't need to pass anything else everything is already uh appended as it should in the main file so now the only thing that I need to do is run this again which will delete compiled build again the binary execute so now we can go ahead and test this so we can get our coffees we can create a new coffee so I'm going to put here uh in the creation delete this so here is the new coffee called delete this obviously uh you know we'll delete that later I'm gonna grab the ID so now this route that we haven't used yet localhost 8080 API V1 coffees coffee and then I'm gonna pass the ID uh newly created and there you go we get the delete this coffee now let's go ahead and update it so that's the only thing uh currently we're gonna have to pass all the values and obviously the ones that we don't want to update we just passed the old values but the ones that we do want to update obviously would change them we don't need to files are created or updated so we'll get rid of that and delete these after update and okay we have no let's see if there's no error there okay so there was an error um let's see SQL state so now I know it's in the SQL State okay so let's go to the services coffee that go let's go to the uh update coffee method and I'm missing the commas very important uh maybe you caught this maybe not but if you didn't well now you know why it didn't work uh here we don't need a Coleman so you can leave that without a comma but these are necessary uh so I'm gonna go ahead and recompile and re-execute so just make sure that we are getting the data I'm gonna do get by ID okay so still we have to delete this coffee then here I'm gonna put delete this after update and now we get the proper uh response delete this after update perfect so now I'm going to go ahead go here make sure that we have everything so we have to leave this after update perfect so I'm gonna delete now the coffee uh successful deletion perfect probably I should put like message um I don't know maybe pass an envelope that way it's easy to to get because otherwise if you get a string it may be a little bit hard um to get so let me see controllers copy.com successfully deletion and we're we're there at the envelope there you go helpers envelope so I'm gonna put uh envelope and I'm gonna do um message um missing company list uh helpers.envelope amazing help preset envelope envelope coffees oh okay okay so I actually need to put this in quotes um message let's see just trying to make this look nicer so actually it should I should be able to do um let me see if I can do that okay uh no successful deletion okay oh wow that was it um actually let me see if I can write it here there you go um so I'm ready to just put it there uh okay so I'm going to maybe I can listen to Port interrupt two copy that go 77 um okay uh maybe I have an error in the deletion uh let's go ahead and do get all coffees yeah so I have uh delete this okay so apparently I had an error so before I continue um let's go to the lead coffee delete from coffees yeah I'm missing the where where ID is equal to one and I guess that you can do this that way it's easier to visualize where you have the area because then it'll tell you in line one line two um I don't know I'll just leave it in one line to be honest I think that's fine um I do want to see if it's specified near the one yeah so it tells you like near where you have the the year so that's fine um so again I'm going to recompile and let's make sure that this last method works so delete this after update and there you go message successful deletion so let's make sure that we don't have uh this coffee anymore and there you go it's deleted perfect we're done with our API and instead of four hours and who knows what I think I shaved off two um a shade of two hours also I did a little bit of um refactoring there were a few methods that I didn't like how they were and the make file I also updated it with the way that I thought that it was easier for you guys to follow so please give it some uh thumbs up uh subscribe please share this um I think this is very useful you can use it to you know expand this and whatnot so please please subscribe share like and uh yeah keep watching and I'll see you guys on the next video bye
Info
Channel: Arturo Filio Villa
Views: 9,675
Rating: undefined out of 5
Keywords: docker, postgres, go, golang, chi, api, go api, sql, raw sql, postgresql
Id: JBrF5yviZKE
Channel Id: undefined
Length: 158min 29sec (9509 seconds)
Published: Wed Jul 05 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.