Tool Directive in Go 1.24
The video introduces the tool directive added in Go 1.24, which allows dependencies to be added as project-specific tools using go get -tool. This avoids global installations and ensures consistent tool versions across a team.
Project-Scoped Tool Management
Tools added via the tool directive are tracked in go.mod and are not removed by go mod tidy. This guarantees reproducible development environments and shared version control for all contributors.
Database Migrations with Goose
The project uses Goose to generate and apply database migrations. By installing it as a tool dependency, migrations can be managed consistently within the project context.
Type-Safe SQL with sqlc
sqlc is configured to convert raw SQL files into type-safe Go code. A configuration file defines the database engine, output locations, package structure, and options such as emitting SQL comments and using specific drivers.
Database Structure and Code Organization
SQL queries are stored in dedicated directories, and generated code is placed in controlled internal packages. This enforces architectural boundaries so that database access occurs only through defined models.
Hot Reloading with Air
Air is added to enable automatic recompilation and live reloading during development. This removes the need to manually restart the Go server after code changes.
Command Automation with Just
The next step involves setting up a Justfile to simplify running tool commands. This streamlines repetitive tasks such as building, generating code, and managing migrations.
So in this project, we are going to be using some tools and we're going to be utilizing what is known as the tool directive,
which was added in Go 1.24, where we can simply use a flag whenever we do a go get to get a dependency into our go.mod file.
That will add it as a tool instead of a, let's call it application dependency.
This makes it a lot easier to have tools in our project that has a specific version
and also that you can share across a team so you don't have one developer using one version of something
and then another developer using another version, which is kind of what we had before where you had to do go install
and that would install a tool globally on your machine instead of having a specific version.
We've already talked a little bit about one of these tools, which is the one called Temple.
But we need more, we need some code generation, we need some what is known as hot reloading,
we need to generate migrations and apply migrations.
So let me just quickly show you how we can add Temple to the project and not globally on our machine.
And the way we do that is we say go get-tool.
Go get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
Get-tool.
It's a nice little tool.
It's a nice little tool.
It's a nice little tool.
Yes.
So see, I also have Temple installed globally on my machine on version, is it just Temple
version?
Yeah.
Temple 03.9.4.3.
But if I check go.mod file, we can see I have a bunch of other tools as well that we will
walk through in just a second, but we can see we have the Temple tool here.
And if I just search, we can see we actually use 0.3.960, which was the one we just added.
So doing this makes it easier to share tools for our project across different developers.
And we can also create commands that makes it easier to work with these tools because
now it's just a go-tool and then the name of the tool and then the command we want to
run.
That's for the next episode where we're going to be setting up something called just file,
which is a modern alternative to make file if you know about that, but it's just a way
that we can quickly create some commands that we're going to be running a lot.
Great.
This was how we can add tools and we only just added Temple.
And some of the other benefits about this is that whenever we want to go.mod.tidy, it
doesn't get removed.
Everyone.
Again.
Accesses the this repository will know exactly what dependencies and which version they have.
Now we also need to do migrations and for that, we're going to be using a tool called
Goose, which also lives on GitHub.
So we just say Goose when I'm using version three, Goose and then the latest.
And now we can.
Generate migration.
In files, which we'll get to later on in the course.
But now we can say go to Goose and they will take a minute to load the first time.
And then now we can actually see it and it goes much faster the second time and we have
access to to this package or this tool called Goose that we can so we can work with migrations
on our database.
Next up, we need something called SQL C, which is what is we're going to be using to.
Take SQL files and then turn them into type save go code and I'm just going to clear this
one out.
I'll say go get to GitHub, GitHub.com/sqlcdev, sqlc commands, sqlc add latest.
And then we need to jump into our database.
And here I have already have set it up.
And sqlc.yaml file, which is how we configure this tool so it knows what engine we are going
to be using.
We're going to be using Postgres.
We can also specify all we're going to specify here, the gen, go and then a packet.
So this is just some information about what is to generate and where it should generate
it.
So we can see here we put the generated code in the models internal.
And then we can see here we put the generated code in the DB directory.
And the way the reason we do this is that we want to keep all database access to come
only through models.
This means that the only way that you can access the database is through our models,
which is where all of our business logic will live.
We also specify we want a file called DB.go entities that go which is going to be technically
the same as model.
We are going to be touching upon what models are and everything.
In depth sooner as you can see what we already talked about what models are what we're going
to look at this code in more depth sooner later on in the course, right?
So I'm just going to differentiate between what we call models and what sqlc defines
as models, even though they are going to be close to each other.
We're also going to emit sql as a comment.
So we can in our model whenever we import one of these generated function, we can also
quickly see what sql is.
Running and then we have to be going to be using the pdx version 5 sql package.
And finally, we want to specify that for any UID in the database.
We want to use this package.
Right and we also need to add a migrations folder and a QVS folder in here is where we're
going to write all of our sql queries.
So for example, user.sql and then in here we can write plain old sql that didn't gets
compiled into type safe go code, right?
Final tool we need.
I'm just going to jump out here is something called air and that's because right now or
up to now we have been starting and stopping our go server manually, which is fine at first
but it can it can slow down development quite quite quickly.
So we want to add something that can hot or life reload our changes.
So whenever we make a change to our to our go file or to our use like the temple files,
we have we have something that recompiles the project so we have we can see our latest
changes and for that we're going to be using this tool called air so gets go get tool you
know.
Right now that come air verse air at latest and we just upgraded from what was in the
code of mud fire in the next episode.
We will set up our just file and configure these tools with some commands so we can more
easily run them without having to say go to command and then the command 11 for example,
and then the command 12 for example,
we need to specify where right here.
We need to specify what it should build and what it should look for with the sql see we
need to specify the input and the output and also the the input path for goose we also
need to specify the input path of like where are my recreation and where should I output
the migration so that we're going to tackle in the next episode.