In Go, structuring your project effectively is crucial for maintainability, usability, and simplicity. The official Go project structure is defined by the Go Modules, which were introduced in Go 1.11. In this answer, we will discuss the typical organization of a Go project using Go Modules and explain the reasoning behind each part of the structure.
1. Root directory:
Your project root directory should be named after your project, and it should contain:
go.mod: A file that defines your project as a Go Module, specifies its dependencies, and sets its import path.
go.sum: A file containing a cryptographic hash of each module version specified in the go.mod, used to ensure integrity and authenticity of the dependencies.
README.md: A file documenting your project and explaining how to use and contribute to it.
.gitignore (or similar for other VCS): A file specifying what files and directories should not be tracked by version control.
main.go: A file that contains your project’s main function, which is the entry point for your program. This file should be placed in the root directory only if the project is a single main package with few dependencies. Otherwise, see the "cmd" directory in item 3.
2. Sub-packages:
For any package other than the main package, create a directory with the package’s name within the root directory. Each of these directories should contain a single Go package, and the package should be named the same as its directory name.
project-root/
|_ go.mod
|_ go.sum
|_ pkg1/
|_ pkg1.go
|_ pkg1_test.go
|_ pkg2/
|_ pkg2.go
|_ pkg2_test.go
3. cmd directory:
If your project contains multiple executable commands or a complex "main" package, create a "cmd" directory within the root directory. Each sub-directory under "cmd" should contain a separate main package for each command your project provides.
project-root/
|_ go.mod
|_ go.sum
|_ cmd/
|_ command1/
|_ main.go
|_ command2/
|_ main.go
4. Internal directory (optional):
If you have packages that should not be used outside your project (i.e., they are internal packages), create an "internal" directory within the root directory, and place these packages there. By convention, the Go compiler will prevent other projects from importing your internal packages.
project-root/
|_ go.mod
|_ go.sum
|_ internal/
|_ internal_pkg1/
|_ internal_pkg1.go
|_ internal_pkg1_test.go
|_ internal_pkg2/
|_ internal_pkg2.go
|_ internal_pkg2_test.go
5. Vendor directory (optional):
If you need to store a copy of your dependencies in your project, run "go mod vendor" to create a "vendor" directory containing your dependencies. This can be useful when you need to cache dependencies or work in an environment without internet access.
In summary, a well-structured Go project should have a clear organization that separates concerns and distinguishes between public, private, and command packages. This enhances readability and maintainability while also adhering to the convention set forth by the Go community.