Hello! Welcome back to our work on the simple-bank API.
In our previous lessons, we successfully initialized our Go module and demystified the go.mod and go.sum files. You now understand how Go manages dependency versions and ensures their integrity for secure, reproducible builds. We have the foundational files in place, but our Go code itself is still waiting for a home.
Today, we'll create that home. We will structure our project's directories according to widely-adopted Go conventions.
Today's Learning Outcome: Organize a multi-package project with cmd/, internal/, and pkg/ directories for the REST API project.
As an experienced engineer with an interest in system design, you know that a well-organized codebase is crucial for maintainability, scalability, and collaboration. While Go is flexible, the community has converged on a set of powerful patterns that provide a clear separation of concerns. Mastering this layout is a key step in setting up projects from scratch.
The "Standard" Go Project Layout
Unlike some frameworks that enforce a rigid structure, Go gives you freedom. However, this freedom has led to the emergence of a de-facto standard, often referred to as the "Standard Go Project Layout." It's not an official mandate from the Go team, but it's so widely used that understanding it makes navigating most modern Go projects much easier.

To get a feel for how this looks in practice, let's watch a brief overview.
How to structure your Go projects
The video 'How to structure your Go projects' by sigfault gives a great introduction to this layout philosophy and mentions the community repository it's based on.
Starting at three minutes and twenty seconds, please watch the repository introduction. This short clip introduces the 'Golang standards project layout' repository, which is the inspiration for the structure we're discussing today.
Now, let's dive into the purpose of each of the three key directories: cmd, internal, and pkg. The following article from Rost Glukhov provides an excellent summary of these concepts.
Go Project Structure: Practices & Patterns | by Rost Glukhov
The article 'Go Project Structure: Practices & Patterns' clearly explains the philosophy behind Go's approach to project organization and the roles of the main directories.
Read the section 'Understanding Go’s Philosophy on Project Structure', followed by the section 'When Should I Use the internal/ Directory versus pkg/?' where you can review the directory comparison. Finally, read 'The Standard Go Project Layout', focusing on the layout overview located just before the directory tree example. This will give you a solid conceptual foundation.
Deconstructing the Core Directories
Let's break down the purpose of each directory in the context of our simple-bank API.
1. The cmd/ Directory: Your Application's Entry Point
The cmd/ directory is where the main packages for your executables live. Each subdirectory within cmd/ corresponds to a single binary your project produces.
- Purpose: To contain the entry points of your application(s).
- Best Practice: The
main.gofiles inside should be minimal. Their only job is to "wire up" the different components of your application (like configuration, logging, and database connections) and start it. All the actual business logic resides in other packages.
For our simple-bank project, we will have one executable: the API server. So, we'll create cmd/api/main.go.
This video segment explains the role of the cmd directory perfectly.
How to structure your Go projects
Let's return to the 'How to structure your Go projects' video for a detailed look at the cmd directory.
Three and a half minutes in, watch the command directory segment. Pay attention to the principle of keeping the main.go file 'really, really thin.'
The official Go documentation also provides guidance that aligns with this convention, especially for server projects.
The official Go documentation, 'Organizing a Go module', reinforces this pattern, particularly for projects that contain both libraries and commands, or are structured as servers.
Please read the sections 'Packages and commands in the same repository' (reviewing mixed layouts) and 'Server project' (reviewing server layouts). Notice how both recommend placing commands in a cmd/ directory.
2. The internal/ Directory: Your Private Business Logic
This is where the vast majority of your application's code will live. The internal/ directory has a special property enforced by the Go compiler: no other Go module can import packages from your internal/ directory.
- Purpose: To house all the core logic, domain models, services, and handlers that are specific to your application and not intended for reuse by external projects.
- Best Practice: This should be your default location for new code. It gives you the freedom to refactor anything inside it without worrying about breaking external consumers, because there can't be any.
Inside internal/, you will typically organize packages by feature or domain (e.g., user, account, storage) rather than by technical layer (e.g., handlers, services).
This video and the official Go docs explain the concept well.
How to structure your Go projects
Here's the segment from the 'How to structure your Go projects' video discussing the internal directory.
About four and a half minutes in, watch the internal directory. The video emphasizes that this is where the 'bread and butter' of your business logic goes.
The official docs also highlight the importance and behavior of the internal directory.
Read the section 'Package or command with supporting packages' to understand the project structure. It clearly states the purpose of internal is to prevent other modules from depending on packages you don't want to expose.
3. The pkg/ Directory: Your Public, Reusable Code
The pkg/ directory is the opposite of internal/. Anything you place here is considered a public library, intended to be imported and used by other projects.
- Purpose: To export reusable code for external consumption.
- Best Practice: Use this directory with caution. Before placing code here, ask yourself: "Is this a general-purpose utility or library that another project could genuinely benefit from?" If the answer is no, it belongs in
internal/. For many applications, especially self-contained servers like our REST API, you may not need apkg/directory at all.
Starting with code in internal/ and moving it to pkg/ later if a need for reuse arises is a safe and common strategy.
How to structure your Go projects
Finally, let's see the explanation for the pkg directory.
Starting around two and a half minutes in, watch the package directory. The key takeaway is that code in pkg is intended for others to import as a dependency.
Hands-On: Structuring the simple-bank Project
Now, let's apply this knowledge. Open a terminal in your simple-bank project directory and create the structure we've discussed.
-
Create the directories:
mkdir -p cmd/api mkdir internalWe are omitting
pkg/for now, as our API server is self-contained. -
Create a placeholder
main.gofile:touch cmd/api/main.go -
Populate
main.go: Opencmd/api/main.goin your editor and add the following code. It's just a simple "Hello, world" for now, but it establishes our entry point.package main import "fmt" func main() { fmt.Println("Starting Simple Bank API server...") }
After these steps, your project structure should look like this:
simple-bank/
├── cmd/
│ └── api/
│ └── main.go
├── internal/
├── go.mod
└── go.sum
You can run your application from the root of the project with:
go run ./cmd/api
You should see the message Starting Simple Bank API server... printed to your console.
Conclusion
Congratulations! You've just laid down the structural skeleton for our simple-bank API. While simple, this layout provides a robust foundation that promotes clean architecture and will scale as our project grows in complexity.
Key Takeaways:
cmd/: Contains the entry points for your executables. Keep themainfunctions here minimal.internal/: The default home for your application's private code. The Go compiler prevents this code from being imported by external projects.pkg/: Used for code that you intend to share as a public library. If you're building a standalone service, you may not need this directory.- This structure, while not officially mandated, is a widely-accepted best practice that enhances project clarity and maintainability.
Next Up
With a solid directory structure in place, the next step is to streamline our development workflow. A well-structured project is easier to build, test, and maintain, but doing everything manually is tedious. In the next lesson, we will write a Makefile with Go-specific targets to automate common tasks like cross-compilation and linting.