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 which 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.
cmddirectory will contain the application-specific code for the executable applications in the project. For now we’ll have just one executable application — the web application — which will live under the
internaldirectory 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.
uidirectory will contain the user-interface assets used by the web application. Specifically, the
ui/htmldirectory will contain HTML templates, and the
ui/staticdirectory 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
internaldirectories, leaving the project root free to hold non-Go assets like UI files, makefiles and module definitions (including our
go.modfile). This can make things easier to manage when it comes to building and deploying your application in the future.
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/cliand it will be able to import and reuse all the code you’ve written under the
Refactoring your existing code
Let’s quickly port the code we’ve already written to use this new structure.
So now our web application consists of multiple Go source code files under the
cmd/web directory. To run these, we can use the
go run command like so:
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.