Project structure and organization
Before we add any more code to our main.go
file, it’s a good time to think how to organize and structure this project.
It’s important to explain upfront that there’s no single right — or even recommended — way to structure web applications in Go. And that’s both good and bad. It means that you have freedom and flexibility over how you organize your code, but it’s also easy to get stuck down a rabbit-hole of uncertainty when trying to decide what the best structure should be.
As you gain experience with Go, you’ll get a feel for which patterns work well for you in different situations. But as a starting point, the best advice I can give you is don’t over-complicate things. Try hard to add structure and complexity only when it’s demonstrably needed.
For this project, we’ll implement an outline structure that follows a popular and tried-and-tested approach. It’s a solid starting point, and you should be able to reuse the general structure in a wide variety of projects.
If you’re following along, make sure that you’re in the root of your project repository and run the following commands:
The structure of your project repository should now look like this:
Let’s take a moment to discuss what each of these directories will be used for.
The
cmd
directory will contain the application-specific code for the executable applications in the project. For now our project will have just one executable application — the web application — which will live under thecmd/web
directory.The
internal
directory will contain the ancillary non-application-specific code used in the project. We’ll use it to hold potentially reusable code like validation helpers and the SQL database models for the project.The
ui
directory will contain the user-interface assets used by the web application. Specifically, theui/html
directory will contain HTML templates, and theui/static
directory will contain static files (like CSS and images).
So why are we using this structure?
There are two big benefits:
It gives a clean separation between Go and non-Go assets. All the Go code we write will live exclusively under the
cmd
andinternal
directories, leaving the project root free to hold non-Go assets like UI files, makefiles and module definitions (including ourgo.mod
file).It scales really nicely if you want to add another executable application to your project. For example, you might want to add a CLI (Command Line Interface) to automate some administrative tasks in the future. With this structure, you could create this CLI application under
cmd/cli
and it will be able to import and reuse all the code you’ve written under theinternal
directory.
Refactoring your existing code
Let’s quickly port the code we’ve already written to this new structure.
So now our web application consists of multiple .go
files under the cmd/web
directory. To run these, we can use the go run
command like so:
Additional information
The internal directory
It’s important to point out that the directory name internal
carries a special meaning and behavior in Go: any packages which live under this directory can only be imported by code inside the parent of the internal
directory. In our case, this means that any packages which live in internal
can only be imported by code inside our snippetbox
project directory.
Or, looking at it the other way, this means that any packages under internal
cannot be imported by code outside of our project.
This is useful because it prevents other codebases from importing and relying on the (potentially unversioned and unsupported) packages in our internal
directory — even if the project code is publicly available somewhere like GitHub.