Creating a source tree
Once you have a new module, it is time to decide how you are going to organize the source files.
How to do it...
There are several established conventions, depending on the project:
- Use a standard layout, such as https://github.com/golang-standards/project-layout.
- A library with a narrow focus can put all the exported names at the module root, with implementation details optionally stored under internal packages. A module that produces a single executable with relatively few or no reusable components can also use the flat directory structure.
For a project like ours that produces an executable, the structure laid out in https://github.com/golang-standards/project-layout fits. So, let’s follow that template:
webform/ go.mod cmd/ webform/ main.go web/ static/ pkg/ ... internal/ ... build/ ci/ package/ configs/
Here, the cmd/webform
directory will contain the main
package. As you can see, this is one instance where the package name does not match the directory it is in. The Go build system will create executables using the directory name, so when you build the main
package under cmd/webform
, you get an executable named webform
. If you have multiple executables built within a single module, you can accommodate them by creating a separate main
package under a directory matching the program name, under the cmd/
directory.
The pkg/
directory will contain the exported packages of the program. These are packages that can be imported and reused in other projects.
If you have packages that are not usable outside this project, you should put them under the internal/
directory. The Go build system recognizes this directory and does not allow you to import packages under internal/
from other packages that are outside the directory containing the internal/
directory. With this setup, all the packages of our webform
program will have access to the packages under internal/
, but it will be inaccessible to packages importing this module.
The web/
directory will contain any web-related assets. In this example, we will have a web/static
directory containing static web pages. You can also add web/templates
to store server-side templates if you have any.
The build/package
directory should have packaging scripts and configuration for cloud, container, packaging systems (dep
, rpm
, pkg
, etc.).
The build/ci
directory should have continuous integration tool scripts and configurations. If the continuous integration tool you are using requires its files to be in a certain directory other than this, you can create symbolic links, or simply put those files where the tool needs them instead of /build/ci
.
The configs/
directory should contain the configuration file templates and default configurations.
You can also see projects that have the main
package under the module root, eliminating the cmd/
directory. This is a common layout when the module has only one executable:
webform/ go.mod go.sum main.go internal/ ... pkg/ ...
Then there are modules without any main
package. These are usually libraries that you can import into your projects. For example, https://github.com/google/uuid contains the popular UUID implementation using a flat directory structure.