Back to blogYouTube Video

Published November 14, 2025

Syncing projects with Google Drive - Part 7 (Reorganizing Codebase)

Can't play the video or having issues? Here's the direct link.

AI Summary

In this video, the developer focuses on codebase maintenance by reorganizing a growing Go project into a modular package structure to improve maintainability before implementing a CLI.

Key Takeaways

  • Maintenance and refactoring are as critical as shipping new features to prevent a 'messy codebase' as a project scales.
  • Moving logic from large files (like `main.go`) into dedicated packages makes the code easier to navigate and manage.
  • Properly exporting fields and functions in Go requires capitalizing the first letter (e.g., changing `api` to `API`).
  • technical_changes平衡点过主点: {

Description

Gonna spend some time cleaning up our messy codebase and organizing things a bit more neatly before we build any more features. This maintenance stuff is just as important as shipping new features, guys. :) Github: https://github.com/hassanaziz0012/drive-syncer-video Full Playlist: https://youtube.com/playlist?list=PLTGiYd8gFivjVHK2xB7TLf7XLW8rmKXRM&si=L97UpFIHgfHbvLMT LINKS Website: https://www.hassandev.me My Book: https://www.hassandev.me/designing-websites X / Twitter: https://x.com/nothassanaziz

Transcript

Auto-generated transcript
Okay guys, welcome back. Quick recap, in the last video we built a couple of new features. Basically we just want to be able to refresh our access tokens and authorize the Google APIs automatically, right? To do that we built a couple of new stuff over here. First of all, this token source object that's going to automatically refresh our access tokens as long as it can and this test access function and this API access status over here this enum and what we use this for and we just use this to you know test access to the API make sure that we can access it and if we can't then we you know do something about it and yeah that's all we built in the last video. In this video, I wanted to set up the CLI but before we can do that, I want to quickly just take a moment to organize all of the files in this whole project because this is, you know, starting to become a pretty large project and I want to just organize all of the files into different packages and stuff. So we're going to do that first. So the very first thing I want to do is I want to create a package called internal slash models. So this is kind of a special name in Go. Anything you put inside internal, it's going to be basically, it's basically going to make our code kind of just like read only for the rest of the packages, right? So basically, and I hope I'm explaining this right, but basically anything you put inside of internal you're not going to be able to modify it from outside of the internal package basically right so i'm just going to put a bunch of models in here so first of all let's just create a file over here call it types.go and this is gonna oh it automatically added the package name package name for me nice um this is going to hold the first of all the drive struct which i have over here where is it there it is we'll just take this all the way over here and it's also going to hold the config and the folder struct so we'll take both of these and as you can see this is going to cause a ton of type errors across the entire project so we're gonna have to solve all of them as well so paste the config and folder over here and now back in the config file over here what i want to do is i want to create another project over here call it config and just move the entire config file over here now we need to import the config object over here as well and for that we can just do something like models dot config and that should work we can do the same thing down here as well and over here and that should solve all of the import errors in this package right by the way you can see that the package name over here that I have also has like a github URL over here and this is just something that I've added in my package name in my module name over here right your module name might be different but the path is still going to be the same right it's just going to be your module name plus the path to the package that you trying to import in this case it just just internal slash models right Now with that the next thing i want to do is i want to move the oauth stuff right all of the oauth authentication stuff in main.go into its own package i'm going to create a package called auth for authorization and create a file inside this called oauth.go and then back in the main function i'm just going to take everything over here that is related to google authentication and we'll just take all of it and place it inside the oauth file over here okay that works no errors as well no import errors or anything also let's create a sync package this is basically going to hold all of the code to synchronize with google drive and all of the uploads and downloads stuff that we build right So for now, I'll just take the sync.go file and place it inside this sync package. Up top over here, let's also change the package name so it works. There it is. And let's solve the import errors as well. Let's say models.drive and make sure to import the correct package over here. And then let's, you know, solve all of the import errors over here as well. This will be models.folder. There we go. Over here as well. models.drive here as well and here and over here models.folder there we go so those errors have been solved now there are a couple of other errors as well for instance you can see that this api field can't be accessed because it's lowercase and go is not going to export lowercase keys so we want to go back to internal models types and we're gonna have to change the config over here to an uppercase as well as the api to an uppercase there we go and now that we've done that we can go back over here and basically just fix all of the errors by just saying drive.api with an uppercase a and just solve all of the errors over here right so let's do that over here we can just use drive.config with you know an uppercase c and here as well and here and here and over here drive.api and that's the last one okay this is the last one there we go and with that all of the errors in the sync package have also been solved Now back in the main.go file, what I want to do is I want to create global variables out of these config and drive structs over here. So what I want to do is I want to take both of these away from over here and place them in the sync package over here as simple variables, right? So let's just say something like DRV and con or just config over here, right? And we'll pass that in over here and just add a var before them, a var keyword. So we're actually creating the variables. Actually, before we proceed, one more thing I want to do is instead of calling this package sync, let's just call this API. I think that's a much better name for this because this is just going to hold stuff regarding the Google Drive API right now we need to solve the import errors as well over here So this read config function it in the config file over here right so what we can do is we can first of all change this to an uppercase r so that we can actually export it right and then what we can do is we can go back to sync.api or not sync.go and just say read config over here and import the config package which is going to be over where is it which one is it okay so my intellisense isn't really giving me that package so what i'm just going to do is i'm just going to copy this whole thing paste it again and just change this to internal slash config over here and then just solve this import error over here uh we do need to change this let me just see why this is happening okay so in config.go we forgot to change the package name let's just change this to main or not not main but to config and then this should work awesome now the new drive function uh this is back in main.go i believe yes it is uh what i'm going to do is i'm just going to take this um connect function create drive service function test access the api access status enum and the new drive function all of these and i'm to place all of them in the oauth file down here all right and let's also solve the import error as well over here models.drive z.api z.api over here as well up here as well let's solve the import errors there we go uh this config should be in uppercase there we go and this api over here should also be in uppercase okay now one more error down here you will notice that uh can cannot define new methods on non local type models dot drive so because this is an internal package object right it's in the internal package code outside the internal package such as this auth package over here cannot access it right and it can it can't define new methods on this drive object because it's an internal type right so to remedy that i'm going to basically just not make it a pointer receiver and just make it a regular function call this connect to drive let's just say and this will take a pointer receiver to the models dot drive object over here so that we can actually access it and assign the appropriate variables and stuff right okay now back in the sync dot go file we need to import this new drive function as well So for that, we can just do the auth package over here and that solves that error as well. And I think the only errors left are in this main.go function now. So let's remove all of the unused imports. Then let's say drv or actually api.drv, right? Because that's the constant that we've defined over here. Not exactly a constant, but more like a global variable that we've defined up here. and actually since we since we're doing all of this inside the sync.go file over here we don't even need to you know pass in the drive anymore like this right because it's we can just access it from the drive up here right the drive variable up here so what we can do instead of all of this is we can basically just change this entire thing i can even rename it so i just have to do it manually uh and just change this to drv over here right capitalize right uppercase letters and then we don even need to pass in this drive in here right we just need to pass in the folder and speaking of folders we can get the folders from let's say api.config and we can get this upload folder function from api.upload folder as well and we don't even need this context anymore so I'm just going to remove that as well and with that all of the errors have been solved so hopefully this whole thing is going to work. I'm going to try to upload something and let's see if that works. Okay so a bit of an error over here invalid memory address or nil pointer due reference. Let me just explain what just happened. We're creating the new drive over here but we're not assigning the api all right? So where is it? In the types over here, you can see that the drive has a API, which is a pointer to drive.service. And the way we assign this is in the OAuth file over here, where we create the drive service and assign it to the d.api field over here, right? Since we haven't called this function, the d.api field is nil, which is why we get the nil pointer dereference error so to fix that let's go over here to main.go i don't know why i forgot to do this and just run auth.connect to drive pass in the api.drb file over here not file the variable force refresh will just be i guess false for now and context can just be ctx which can be context.background up here now with all that done let's try running this whole thing again Okay, so this time it's actually working. It saved the token to token.json. The token is valid. So we tested the API access as well. And then we started the upload process. And it's just uploading a bunch of files, skipping the ones I want to skip, creating subfolders and everything else as well. Quick little check in my Google Drive as well. You can see that it uploaded all of the new organized files as well over here, right? So everything is organized a lot better in internal models. all the new packages auth api everything is over here right so all of this got synchronized perfectly as well the upload process works the functionality everything works and we were able to organize all of our code into some you know a lot better like packages and stuff right now we're actually ready to build a cli at last which is what i'm gonna do in the next video i don't know why i keep procrastinating on this but uh yeah i'm going to build the cli in the next video For this video, I just wanted to organize everything a lot better so it's just easier to work with, right? Because I just had so much code in so little files over here, right? Like most of my code was in the main.go file and then in the sync.go file over here, right? At least this way, it's a lot more organized. In fact, even in the sync.go file, we could organize it even further into a bunch of smaller files inside this API package. I'm not going to do that right now, but just an idea, right? So yeah, I'm gonna end the video over there and in the next video Finally, we're going to build a CLI so we can interact with this application and really make it more usable, right? Stay tuned for that. Thank you for watching this one and I'll see you in the next video boys

Share this article

All great things started with a conversation

If you've got a cool project or opportunity and you want me to be a part of it, set up a free meeting with me here, and let's talk. 😊