This article will describe the common approaches which are used for structuring Golang applications. Golang does not have an official guideline to structure the project, so it is an opinionated guideline to structure Go applications.
Go is an amazing language, it is simply easy to learn and gives you a lot of tooling out of the box. Most of the Gophers who started learning the Golang they have one thing in common, they struggle to figure out how to structure applications due to the lack of official guidelines. The main approach for structuring Golang applications is to start out simple, but with the flexibility to grow.
There are no strict rules for the directory structure or how to organize Go project files in a specific way. It is bad because it is easy to create a mess and good because the structure of the project can be built according to the taste of the developer.
The good structure is the one which is consistent across the project. There is nothing worse than coming to the codebase and seeing one part of code done in one way and another part done another way. Especially if you are not an original author and you just coming to the new codebase and you have no idea which structure you should follow. The good code structure must be easy to understand and navigate and it should make sense. Good code structure will make your life easy as a programmer and fun.
Go developers typically follow certain patterns in laying out the files and directories in their projects. They usually follow these patterns because it works for them and their fellow developers. In my opinion, the organisation should follow the same structure for all the projects they have for the Golang application, as this way it makes the developers more productive.
Structuring Project Files in Go
The better way to organize a Go project is to put relevant Go code files into a subdirectory under the main directory for the project so that other parts of the project are able to find the service APIs and use it.
Keeping all source files under the same directory is not a good idea, because it makes the code files cluttered, as a result, you spend most of the time looking for the correct file. Most experienced developers know about it.
For the purpose of demonstrating a project layout, we would be creating a demo project called "go-layout".
This is the tree structure of the sample project type. Below we would be explaining what each folder does:
/cmd
The folder will contain the main applications for this project.
There might be more than 1 application within cmd folder, and each application should have its own folder so the path would be cmd -> applicationNameFolder
.
The directory name for each application should match the name of the executable you want to have, for example, cmd/myapp
.
It is important that we don't put a lot of code in the application directory. If you believe that the code can be imported and used in other projects, it is better to place these codes in the pkg
directory.
It is common practice to have a small main
function that imports and invokes the code from the /internal
and pkg
directories.
Please check out some of the successful projects which are written in Golang.
Examples:
- https://github.com/kubernetes/kubernetes/tree/master/cmd
- https://github.com/ethereum/go-ethereum/tree/master/cmd
- https://github.com/influxdata/influxdb/tree/master/cmd
/api
This folder can have OpenAPI/Swagger specs, JSON schema files, and protocol definition files.
Example:
/build
This folder can have folders/files which are relevant to the packaging and Continuous Integration files, such as Docker and scripts.
Put your CI configurations and scripts in the /build/ci
directory.
Examples:
/configs
It can have configuration file templates or default configs.
/examples
You can include examples of your applications and/or public libraries.
Examples:
- https://github.com/hashicorp/packer/tree/main/examples
- https://github.com/docker-slim/docker-slim/tree/master/examples
/internal
Private application and library code. This is the code you don't want others importing into their applications or libraries. Note that this layout pattern is enforced by the Go compiler itself. Note that you are not limited to the top-level internal directory. You can have more than one internal directory at any level of your project tree.
You can optionally add a bit of extra structure to your internal packages to separate your shared and non-shared internal code. It's not required (especially for smaller projects), but it's nice to have visual clues showing the intended package use.
Your actual application code can go in the /internal/app
directory (e.g., /internal/app/myapp) and the code shared by those apps in the /internal/pkg directory (e.g., /internal/pkg/myprivlib).
The folder /internal/pkg
contains packages that are not specific to this application. These packages could theoretically be extracted into a standalone public package if they provide utility.
Examples:
- https://github.com/hashicorp/terraform/tree/master/internal https://github.com/influxdata/influxdb/tree/master/internal
/pkg
Library codes which can be used by external applications (e.g. /pkg/mypubliclib
). Other projects will import these libraries expecting them to work, so double-check before you put something here.
Note that the internal
directory is a better way to ensure your private packages are not importable because it is enforced by Go.
it is ok not to use /pkg
directory if your app project is really small and where an extra level of nesting does not add much value. But you need to think about it when your project is getting big, and your root directory gets busy.
Examples:
- https://github.com/kubernetes/kubernetes/tree/master/pkg
- https://github.com/helm/helm/tree/master/pkg
/third_party
External helper tools, forked code and other 3rd party utilities (e.g., Swagger UI).
/web
Web application-specific components: static web assets, server-side templates and SPAs.
/http
You might want to expose your application through several means of communication such as rest-api and grpc.
This way you can have a separate separation between each type of communication layer by creating a separate directory such as /http/rest
or /http/grpc
You can download the full project layout template from my GitHub (https://github.com/fir1/go-layout).
The end
Hopefully, this tutorial gave you some insights on how to structure your next Golang applications.
Thatβs it for this blog. Please feel free to comment your views on this blog. Thanks for your time reading this blog and hope it was useful.
Happy learning and sharing.
Top comments (1)
Where did the inspiration for this package structure originate from? Good code organization follows a design pattern or architecture. Examples are Clean Architecture or Domain Driven Design.