bouncer
← Back

Kelvin Mai · 632 views · 18 likes

Analysis Summary

10% Minimal Influence
mildmoderatesevere

“This video is a straightforward technical guide; be aware that the specific architectural choices (like package naming) are the creator's personal preferences rather than universal industry standards.”

Transparency Transparent
Human Detected
98%

Signals

The video features a human developer providing live commentary during a coding session, characterized by natural verbal stumbles, spontaneous word choices, and specific references to the visual layout of the IDE.

Natural Speech Patterns Transcript contains filler words ('uh', 'all right'), self-corrections ('converges or no what's the word'), and informal phrasing ('more of a nitpick').
Live Coding Context The narrator describes real-time actions ('let's put this to the side', 'I'll just put this over here') that align with manual screen interaction.
Personal Identity Narrator introduces himself by name (Kelvin) and links to personal social media and GitHub repositories.

Worth Noting

Positive elements

  • This video provides a detailed, practical look at structuring Go applications, specifically handling custom error types and database schema migrations.

Influence Dimensions

How are these scored?
About this analysis

Knowing about these techniques makes them visible, not powerless. The ones that work best on you are the ones that match beliefs you already hold.

This analysis is a tool for your own thinking — what you do with it is up to you.

Analyzed March 13, 2026 at 16:07 UTC Model google/gemini-3-flash-preview-20251217 Prompt Pack bouncer_influence_analyzer 2026-03-08a App Version 0.1.0
Transcript

hey everyone my name is Kelvin I'm a developer and I make free tutorial content if you like this kind of thing consider subscribing and liking the video and if you want to support me in other ways you're always welcome to buy me a coffee all right before we move on to Crea our entities or the other schemas I want to do a little bit of refactoring and the first thing is more of a nitpick but this the responses are in a router package and I want this to be a sub package called response so I'm going to move response and error into it which means both of these we have to change the package to response so now the response. go file and the error. go file are in the package of response and because of the name change we're going to need to change the uh import path as well as the package that we're calling it so here be response. default error Handler there's one in routes. go so here we also need to change this as well as the return in our health check and this also goes for all of our fiber handlers so luckily we only have one controller so it's not too many different places but in o. or o controller we'll change all the router. created to response. created or this will be response. okay and this refactor is mainly just because I wanted to say response Dot and the status response so it is a minor nitpick on the wording but in addition I want to have some more type safety so inside of models I'll make a new file called response and here we're going to make some strs just to describe the structure of our API responses and let's put this to the side so we're it's actually trying to mirror the Json map that we created over here so we have success data and meta so this mirrors our API responses this also means we can use these strs in response so the turn of generate metadata is no longer just an interface it's an API metadata which also means we need to update these keys and then similarly with API response I'll just put this over here so that we have more space this is now going to be a model. API response and also update these keys and now we have uh proper models for type safety and then finally the last thing I want to do uh before we start this section is to have a bit of better error handling and to explain what I actually want is that right now we're doing a log on the error inside the default error Handler but uh I want to log out the raw error which if we go to O we aren't really doing that uh when we do if error is not n we just send a a message and this makes sense because we want to offis skate it we don't want to expose the error to the user but in our own server we want to actually read what went wrong so to change a few things we're going to go back into response and add a new struct called API error and for this to be compatible with the goang error we have to fulfill the interface of that it having an error method that provides a string when being called now this is the basic um fiber error we're going to extend it a little bit but it's a good starting point I also want a noble field called Data just in case we want to spend more than just a string message and then not to mix things up with the data part of the API API response I'm going to add a field called API error or error on the response so that we could send it to the user and and I do want it to be nullable so I'm going to make sure that this is a pointer as well but with this intact we go back to error and update this a little bit so in our Json here this is now going to be an API response so it still um converges or no what's the word it's still the same as our regular other responses uh we do have an error here because now the error model itself is more than just a string but I think we'll come back to it to it instead we're going to create a Constructor to create a new API eror and I believe that's everything that we need let me we didn't add any other fields so that should be correct no I think that's correct I will keep that and then that just means we need to change this part of the default error Handler so let me just get rid of this so I can start from scratch so first I'm going to do a conversion of the raw error into an API error and then if it's not okay we also want to check if it's a fiber error that way we can check if it's a default error from our from fiber or a custom error from our functionality I think that's correct so far all right so we no longer need code here and this error could just respond with E and this will be e. code okay believe that's correct and then lastly for every possible error uh we're just going to make a simple error function or simple helper function no actually I do want the error in here so I'm going do error error so then we could add a log here that way we could have log out the raw error which is the whole point of making this refactor but going down we're going to make um helper functions so that these things will have less arguments that we could call where wherever we need so so far we have a bad request error and unauthorized error so these are the API errors that we're going to create unauthorized is going to be a little special because we want to provide a string that's um secure and safe to the user or safe to expose to the user but I believe that's everything we need here so let's just update our off controller once again and and we're going to go down the list of all of our errors created and send back the raw error so this one is uh bad request error error bad request error error unauthorized registration eror registration I think that's correct now it's a login okay those are all unauthorized errors and then finally in me we'll do a invalid credentials as the unauthorized error here uh this also reminds me in our middleware we should also change this error Handler as well so now we do response. bad request or unauthorized and if we are responding with other status codes we should make those as we go along but I believe everything is in place now where I'm happy with the response um structures so that means this is a good spot to make a commit so I'll cons solid that's the right word all right so this commit is going to be refactor responses and that should be good so it's actually time to plan out our data models and I'm using a website called DB DB diagram. which just makes it a little bit easier but I went ahead and already made the models that we're going to be using the main model that we're going to be creating for this application is transactions and it's going to have all these different um properties we're going to add the created and updated that that we've added to all of our models but I'm also go with the title and the amount which makes sense also a currency because I think it'll be useful for anyone following this tutorial to not just default to USD enum for the transaction type so it could be either an income or an expense so money coming in or out and then I've also added a category model this is more just to like show like what kind of transaction it was and like where it's going so it could be like a grocery expense or a freelance income so I think that's just useful data to have and both of which are going to be dependent on the user so only the current user has access to these data that pertains to them but with that let's actually write the squl for this and let's add a new for file this is 03 create transaction that's equal and that's the default boiler plate what else did I add on this uh user ID text preferences us ID I believe that's correct syntax uh we also need a category so let's do that okay good think that's that's correct so far so that means this is category ID all right what else did I add on this um title is text amount is numeric and then finally we need to create an enum create type as enum so this will be income all right so I believe all this is the correct syntax nothing too crazy in terms of the sequel that we WR wrote um something new is probably the inum syntax as well as the numeric uh how numerics work is we're giving the amount of btes that we're going to use before and after the the decimal point so I'm defaulting to two places after decimal I believe most currencies don't have anything more than that so that should be fine if not uh feel free to edit that and make it a little bit more robust but uh because this is all inside the Docker entry point uh what we can do is uh kill your current Docker um container image uh remove it and just call dock compose up again and this should just run all of the subsequent SQL that we Rewritten which this should be a good indicator that it's working and then from here the next step is to add these into our schemas model which is not there it's it's in models SL schemas no no no no no no no oh this actually should be no no okay I believe everything here is correct so it should look something like this no new Concepts here so I don't think I need to actually like say anything but those are the models and I think this is also a good time to make a small commit not of code but it's a good stopping point before we set out to create the controllers and services to for the crud part of our application so I just wanted to Define their transaction models or data models and push this all right so from here I think we're going to just go through the services and controller of the categories so let's do the service first and I always forget to make these a pointer but so similar to our user service we're going to create a struct and a Constructor and I believe for the category service it's going to be basic crud so we'll just have the the five basic crud operations we're going to get all a list all of them but since these are related to the user ID we need to get it by the user ID get by ID create update and delete are pretty much self-explanatory but let's go through each one so get all my user id of course will need the user ID and this query is going to be a simple select all or simple select star from categories where user ID is the provided argument and it's also important here that we're using the dot select operator this will give us the list of everything that comes back so the return here is a slice of categories and an error and this is still mad because this needs to be a slice so there that's fixed next we have get by ID and get by ID is essentially the same thing except we're only getting one and the argument is now the ID of that that category and the returns here is one category and the error well I suppose this is actually a pointer because this is nullable so or nullable so I need do a reference to and then the pointer as the return now for create we just need the user ID and the title and that's going to both be strings and just like how we did at the user service we're going to do a quy x to do the insert providing user ID and Title Here for the necessary things add the error checking which means this is a good time to add the return statement and then for the rows that we want to return we need a stru scan which means first we need to call row. next and then row. stru scan so that we can bind the data into the model that we have for category and then finally return it and I want to do delete first just cuz it's easier essentially it's going to be the same steps we're still going to be using query X so most of this is going to be the same so I'll copy it and paste it down here the only thing that changes is the query itself so now it's a delete from category where ID is ID and return the category as well as the error now for update we still need to find the category that we're updating so we'll need the ID but we also need to think about what fields are updatable and thankfully our category schem is pretty simple we only really want to update the title we haven't really made this or expanded this schema to actually be more useful than that so it'll just be a title for now so that means we'll also need the title here and now we just need to set the query uh I actually want the ID to be the first argument so let's do it this way and I believe that's everything that we need for our service all right I instantiated all of our services in server main I believe so that means it needs to be over here and start so this is the category service service do new category service and we need the database undefined new category service oh that's why I made a mistake this is not a method it's a Constructor should be a function there we go that's better um we don't currently have a controller set up so I'm going to comment this out for now and we can go ahead and start the um category controller so this will be category. go package controller and I believe all we really need here is the service so so that should be the boiler plate for our category controller and let's stub out all of our methods and remember that they're all fiber controllers so all of them will take in the context and return an error and I believe all of these we actually do want them to be authenticated so I'm just going to quickly grab these three lines here and add it over to the front H you what I'm going to update the off controller of little bit because I don't want the username to be the subject I want the ID so I'm going to do a small tangent of updating the authorization a bit so subject is being signed here and create token uh I mean I don't really need to change that I just want this to be ID and that means I have to update the call to create token and pass in the user. ID there and there which now means that this is the incorrect service call we want to do get by ID of the user ID so we're going to update or we're going to add a new call in user. go or the user service which will just be basically a clone of this function but instead of get by username this will be get by ID and we'll just change all this to ID and that should fix the entire flow so that our token has the user ID not their username that'll make the things a little bit easier for authorizing some of these things in the list or in the the crud operations that needs authentication if error. n return this will be a not found right so that also means We'll add a new error response error so this is not a bad request this is not unauthorized this is eror not found uh we can just make this a little easier not even send a message I just do resource not found I think that's fine but this is the error that we're going to return from here error not found and we do want the raw error so we'll pass that in otherwise this is a response okay so forget is going to be a little different we actually want the ID from the prams which we be we will be passing in through fiber when we set up our routes but other than that passing the ID everything else Remains the Same with one change and that is we're going to check the user ID on the user ID of the token uh which means we actually do need these three again so let me just add that here and change this to user ID and if the user IDs don't match then we'll just send unauthorized and with this logic it means that only the current user can see their own categories so with create we do need the user ID so we'll take that from the token and we also need the title and that's going to come from the Json body so if we go back to the off controller it'll look something like this the only difference is we're going to make another a new input and it does seem a little Overkill since it's only one attribute but just to preserve the convention that is throughout the rest of our application let's also add this and instead of off model this is the category inputs but from here we could call our services create passing in the user ID as well as the input. title and if something goes wrong I I think this is still considered a bad request so I'll do this otherwise is a response. created and that will conclude our creates so update so same thing we're starting with the user ID and body part input ooh actually we need to make an update to the service so I just remember that um we're going to want to add a another constraint to both update and delete and all I'm going to do is add user ID to both the update and delete functions and update their SQL queries to include the user ID both of which is going to be a where and so it'll have to have both constraints and this way we'll have extra authentic or authorization security so that a user can't accidentally update a category by another user and this security is in the data layer so it's more secure than being in the API layer if that makes sense so back at the category in update we also want the ID pram so I'll just add it right there underneath the user ID and the order is ID user ID and title so that should be the correct order I suppose like a database error would be a better one but I think it's still use the same status code so I don't even know if like there's a really a necessary reason to make a new error response but eh and then for delete I believe we just add pretty much the same thing uh the only thing we're updating here is the method call so this will be delete which doesn't need a title so we can get rid of the body parsing here and that will complete our controller which now means we can add it to our server main so this is controller. new category controller which takes in CS and then we need to update setup routes to take in both of these controllers uh where is that here so I guess CC categor controller and then we could actually just make a new group here here get post put so that's all the CR stuff within this route group we want all these routes to be authenticated so every single one is going to need a token just to go through and in main.go we can finally just do comma CC and all of that will now allow us to test these new routes so let's do that so dock go up and air all right let's run through all of this let's see if we're still logged in and cannot reuse this token so wait how about now nope it's expired so that means we'll need to log in and all right I didn't see it uh fine I'll just register all right cool let's grab this token now I'm just going to make a new request in Insomniac just so that we have the login ready to go whenever we restart the application we're at Port 4,000 and we need to go to categories which I don't remember how I spelled it setup routes no it's singular okay [Music] fine all right well that's good it's empty which I mean we did kind of expect but let's do a create and and and we only need a title so let's just make a utilities category right now which works uh let's also just make some more random ones so travel luxury I guess is a good category so now at get all we should get all three which is correct and let's grab the ID for luxury so that'll be slash this which gives us that singular one where we get to do an [Music] update which also works and let's test a delete where we're not logged in and we get a correct error code so that's technically correct but if we are logged [Music] in the delete is successful so that's good so all the routes are working that we created for categories so let's quickly make a commit that we completed the categories and we've also updated the JWT payload to use the user ID instead of the username so I think it's kind of important to add that to the commit description as well but now we can start doing the transactions so we're going to follow similar steps we're going to create a transaction Service First and I do want to start with just the simple crud operators we'll do the full list or select all afterwards just because it's a little bit more involved and we're going to focus on pagination so here's get by ID so for creating an update I think I going do something a little different which is inside of inputs I'm going to create a new input and this will have all the attributes that we want from the actual schema itself which in here is going to be this portion right here so I'm going to paste that in here uh we could probably get rid of the DB struct literal tag we don't really need that here um I'm also going to get rid of the user ID so that means here we're going to need uh inputs which is going to be model do transaction input as well as the user ID and then in update we're going to have the same thing but I also want the ID of the thing we're updating first so we'll do ID string first actually let's put the strings first and the input as a last last argument so now in create we're going to actually build a transaction with the user ID and the model transaction or the input wait what else do I have on this category ID title amount currency okay uh I think that's it right I wish go had a spread operator cuz I all right but this time instead of using query X since we're basing our query on a struct we're going to use DB do named query and let me just do this we're going to pass in prepared as the structor we're going to be using since we have a prepared struct we're going to be using the colon Syntax for each column and then the rest of the function is going to be exactly what you would expect from using db. query X so we'll return error if there is an error and then if not we'll struct scan into a transaction um bar and then return that results and then for update we're going to have basically the same functionality with only changing the the query itself so this will be update okay I think that's the correct query so we have category ID title amount currency type the dates are automatic and then we're setting it with a constraint of ID and user ID so good so far now let's do delete all right so delete is function identical to the one that we did from categories we only need the ID and the user ID so we don't actually need to do any fancy name query so that's why we're using query X here but this uh completes our transaction as of now let's go ahead and create our controller D all right so once again boiler plate and I think for all the credit operations we could copy uh everything from get down of our category and just paste it here and we'll go down the list but I think all we need to do is change category controller here to transaction controller or actually just replacing all the instances of uh category with transactions and these should all work correctly but here's the completed get all right creates a little different instead of doing input. title we actually want to pass in the entire input itself and then with update ID user ID input okay that's a correct order so that's update and then delete is should be correct now we'll do another review of putting all this together in main so service first then the controller which takes in a surface and then with setup routes we need to pass it in so and make sure that setup routes also takes in the new controller so that's adding it here TC is controller transaction controller and then we'll go down the list and delete so there's our crud routes and remember we are saving the root route for last so that we can work on pagination but with all of this you can go ahead now and test it out so I'm doing a little bit of testing and I just want to go through what I need to fix um so both in schema and inputs I mistakenly typed amount as a string so we need to change that to a FL and I'm going to with float 32 I don't think we need that much Precision for currency amounts but uh you go with float 64 if you really think you need it so that's transaction in schemas and the transaction input as well and then currently in my testing I also remember that our database schemas all have uh plural names so I'm going to also add or I'm going to fix that because because they're all singular in the code at the moment so I'm basically adding s's to all the transactions or references to the transaction table so this should be plural so transactions s and with that saved this now should post violates foreign key conate transaction category ID for what I don't what category uncore ID OHA I'm an idiot in Json it should be camel case rows are closed that's a new one okay so kind of dumb but in create I forgot to add the returning star and that'll fix the that issue and in update uh also done but I forgot to add commas but now all of our Crow operations should be working correctly now let's start on our pagination so I think for pagination let's start in the controller layer and then work our way back to the data layer so up at top let's make a new function or method where we're going to call get all or we're going to name it get all and it's essentially just another fiber Handler and as with get we're going to need everything from the user JWT but also from here we're also going to want the page and Page size and we're going to use the query method on the fiber context um we going to expect it all to be an in so we will let fiber do the conversion for us and we don't have to do it ourselves let's use underscores that that would make more sense so for page I want to default it to zero but for page size let's have a let's go with a default to 25 I think that's should be fine but with all of this we will now know that our service is going to need page page size and user ID so we'll come back to get all to finish it out but in the servers let's make a new method so get all will return a slice of transaction and an error and we did say we want the user ID which is a string and then page and Page size which are both ins so I actually don't need this all right we could start with the simple select star statement let's change this to a template string so that we can also add limit and offset so limit is the page size and then the offset is uh we can make a new variable for that and we can put that here so offset basically is the starting point of our s so for every subsequent page we're going to skip the whatever amount of items we've already seen and just return the rest I think that's good for now let's add it back to our controller and this is to get all we need the user ID page and Page size I think this is actually not found eror maybe if there's an error uh it would actually be a database error but this will be fine for now but if everything's okay then we'll do response. okay we need these contacts and fiber. and I think that should do it right let's run a quick test so log in grab token transaction update token and we're doing get uh all transactions so we don't need this method not allowed oh right we need to add this method into our routes and that is in routes transaction. getet PC do get all all right let's try that again send resource not found what offset must not be negative oh I think we actually want this to default to one so so the page is one page size is 25 send there's all of our transactions which is good now let's add some query parameters uh let's just do page two that should be empty and then if we do one and Page size it is let's go with three there's three and that's correct all right so pagination is working as we need I thought that would be more complicated um what was my original plan okay so I think I procrastinated enough on doing the front end so let's actually just finish this up and all right so all we need to do now before we start on the front end is to make sure that we have cores enabled where is our Fiber app here we go so it's server Main and we're just going to add this here but we need this import um the middleware for Cores so that inside of our new server where we have it we can add app.use cores. new and that should be everything that we need for now um on our back end and we can start on this the front end uh but before that let's just kill this and make sure that we commit everything okay so this will be our commit we okay I think that's a good description so we completed our transactions and that'll be our commit uh the description is including all the minor mini steps that we did but that should be it and good to go so we can push this and now we can start on the front end

Video description

------ Links Source - https://github.com/kelvin-mai ------ Social Links LinkedIn - https://www.linkedin.com/in/kelvin-mai-461756152/ Twitter - https://twitter.com/kelvinmai ------ Chapters 00:00 Introduction 00:11 Refactor Responses 02:36 Improve Error Handling 07:37 Setup Data Models 11:45 Begin Categories CRUD 16:09 Update JWT Subject 19:56 Add User ID constraint to category service 24:48 Transactions CRUD 30:55 Add Pagination 34:34 Enable CORS

© 2026 GrayBeam Technology Privacy v0.1.0 · ac93850 · 2026-04-03 22:43 UTC