Go Project
External
- https://github.com/golang-standards/project-layout
- https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1
Internal
TODO
- Where are the generated executables placed? In a transient
./build
? This is how YuniKorn does it. The project layout document does not say anything about it.
Overview
This page collects recommendation and facts about Go projects and it was mainly written with the assumption that one project lives in its own repository and contains a single module, as described in Packages, Modules, Projects and Repositories. Of course project can contain multiple modules, but that is not recommended.
A Java-style /src
is not recommended.
Project Layout
This layout is inspired by:
. ├── api │ ├── openapi.yaml │ ├── openapi-spec.gen.go # Generated from openapi.yaml │ ├── openapi-types.gen.go # Generated from openapi.yaml │ └── file1.proto, ... ├── protobuf # Alternative directory for Protocol Buffer files. │ ├── somepkgpb │ │ ├── file1.proto │ │ └── file2.proto │ └── someotherpkgpb │ ├── file3.proto │ └── file4.proto │ ├── cmd │ ├── myserver │ │ └── main.go │ └── myclient │ └── main.go ├── pkg ├── internal │ └── server │ └── openapi-http-server.gen.go # Generated from openapi.yaml ├── config ├── scripts │ ├── build-myserver.sh │ └── build-myclient.sh ├── docs ├── Makefile ├── README.md ├── go.mod ├── go.sum └── .gitignore
Directories
api
The directory contains OpenAPI specification files, JSON schema files, protocol definition files.
One option is to also place the type and the spec files generated by the OpenAPI code generator, as shown in the layout above. For more details on how to generate code from the OpenAPI specification, see:
Protocol Buffer Support
Protocol Buffer files can be placed in this directory. Alternatively, a protobuf
or a protocol
can be used. Also see:
cmd
The directory contains the main applications for this project. If the project has multiple executables, the code fore each should live under their own directory, and the name of the directory should match the name of the executable. This convention aligns with the behavior of the go build
command, which names the executable after the name of its parent directory. The Go code file name can be either main.go
, which is preferred, or the name of the command myserver.go
. Different projects use one of these two conventions. Do not put a lot of code in the /cmd
directory. If you think the code can be imported and used in other projects, put it in the /pkg
directory. If the code is not reusable, put it in the /internal
directory. It's common to have a small main
function that imports and invokes the code from the /internal
and /pkg
directories and nothing else.
main.go
Some project name this file myserver.go
.
package main
import "fmt"
func main() {
fmt.Print("starting my service ...\n")
}
pkg
Place here the packages publicly exported by the module. The presence of a package in this directory shows that it is OK to be used by external applications. Other projects will import these libraries expecting the to work, so think twice before putting something there. The internal
directory is a better way to ensure your private packages are not importable, because this is enforced by the complier.
internal
This is the module code that shouldn't be imported by the module's dependent application or libraries. This layout pattern is enforced by the Go compiler. For more details, see:
config
Configuration file templates and default configuration.
scripts
This directory contain scripts to perform various build functions, install, analysis, etc.
They should be used by Makefile
, which will keep the file small and simple.
docs
Generated documentation, user documentation, design documentation.
Files
Makefile
Makefile
should prefer to use scripts from the /scripts
directory, which should keep it simple.
.PHONY: build
build: myserver myclient
myserver:
"$(CURDIR)/scripts/build-myserver.sh"
myserver:
"$(CURDIR)/scripts/build-myclient.sh"
Example to process: https://github.com/hashicorp/terraform/blob/main/Makefile
Generated Code
Placed within the regular layout, though files have a .gen.go
extension.
Project Bootstrap
Follow the same template as Python Project Bootstrap. Use and possibly merge with Go.mod#Initialize_go.mod
Microservice-based Project Layout
TODO
- Finish parsing https://github.com/golang-standards/project-layout
- Integrate Vendoring