patterngoCritical
What is a sensible way to layout a Go project
Viewed 0 times
projectsensiblewhatwaylayout
Problem
I have a go project that is starting to become more complex, and want to lay the filesystem out in such a way to reduce pain.
Are there some good examples out there of what makes sense?
Are there some good examples out there of what makes sense?
Solution
2023: general advice from Christoph Berger in "The one-and-only, must-have, eternal Go project layout":
Spoiler Alert: There is no such thing. The optimal Go project layout depends on your exact use case.
That offers a counter point to the controversial (and non-official) repository
"#117: this is not a standard Go project layout".
Update May 2013: the official documentation is in the section "Code organization"
Go code must be kept inside a workspace.
A workspace is a directory hierarchy with three directories at its root:
The
The
Update July 2014: see "Structuring Applications in Go" from Ben Johnson
That article include tips like:
Separate your binary from your application
combining the
The best way I’ve found to fix this is to simply use a “
Library driven development
Moving the
Sometimes you might want users to interact in multiple ways so you create multiple binaries.
For example, if you had an “
You can easily do this by organizing your project like this:
Users can install your “adder” application binaries with “go get” using an ellipsis:
And voila, your user has “
Don’t go crazy with subpackages
Usually my project’s types are all very related so it fits better from a usability and API standpoint.
These types can also take advantage of calling unexported between them which keeps the API small and clear.
Note: that last practice isn't always good:
Sorry I just cant agree with this practice.
Separating type to files helps code management, readability, maintenancability, testability.
It may also ensure single responsibility and the follow of open/closed principle…
The rule for not allowing circular dependency is to force we have a clear structure of the packages.
(Alternative February 2013, regarding
You can find the classic layout illustrated in "GitHub Code Layout":
The app and both libraries live on Github, each in its own repository.
Your code layout would look like this:
Each folder under
Tha
Spoiler Alert: There is no such thing. The optimal Go project layout depends on your exact use case.
That offers a counter point to the controversial (and non-official) repository
golang-standards/project-layout, with its contentious issue:"#117: this is not a standard Go project layout".
Update May 2013: the official documentation is in the section "Code organization"
Go code must be kept inside a workspace.
A workspace is a directory hierarchy with three directories at its root:
srccontains Go source files organized into packages (one package per directory),
pkgcontains package objects, and
bincontains executable commands.
The
go tool builds source packages and installs the resulting binaries to the pkg and bin directories.The
src subdirectory typically contains multiple version control repositories (such as for Git or Mercurial) that track the development of one or more source packages.bin/
streak # command executable
todo # command executable
pkg/
linux_amd64/
code.google.com/p/goauth2/
oauth.a # package object
github.com/nf/todo/
task.a # package object
src/
code.google.com/p/goauth2/
.hg/ # mercurial repository metadata
oauth/
oauth.go # package source
oauth_test.go # test sourceUpdate July 2014: see "Structuring Applications in Go" from Ben Johnson
That article include tips like:
Separate your binary from your application
combining the
main.go file and my application logic in the same package has two consequences:- It makes my application unusable as a library.
- I can only have one application binary.
The best way I’ve found to fix this is to simply use a “
cmd” directory in my project where each of its subdirectories is an application binary.camlistore/
cmd/
camget/
main.go
cammount/
main.go
camput/
main.go
camtool/
main.goLibrary driven development
Moving the
main.go file out of your root allows you to build your application from the perspective of a library. Your application binary is simply a client of your application’s library.Sometimes you might want users to interact in multiple ways so you create multiple binaries.
For example, if you had an “
adder” package that that let users add numbers together, you may want to release a command line version as well as a web version.You can easily do this by organizing your project like this:
adder/
adder.go
cmd/
adder/
main.go
adder-server/
main.goUsers can install your “adder” application binaries with “go get” using an ellipsis:
$ go get github.com/benbjohnson/adder/...And voila, your user has “
adder” and “adder-server” installed!Don’t go crazy with subpackages
Usually my project’s types are all very related so it fits better from a usability and API standpoint.
These types can also take advantage of calling unexported between them which keeps the API small and clear.
- Group related types and code together in each file. If your types and functions are well organized then I find that files tend to be between 200 and 500 SLOC. This might sound like a lot but I find it easy to navigate. 1000 SLOC is usually my upper limit for a single file.
- Organize the most important type at the top of the file and add types in decreasing importance towards the bottom of the file.
- Once your application starts getting above 10,000 SLOC you should seriously evaluate whether it can be broken into smaller projects.
Note: that last practice isn't always good:
Sorry I just cant agree with this practice.
Separating type to files helps code management, readability, maintenancability, testability.
It may also ensure single responsibility and the follow of open/closed principle…
The rule for not allowing circular dependency is to force we have a clear structure of the packages.
(Alternative February 2013, regarding
src only)You can find the classic layout illustrated in "GitHub Code Layout":
The app and both libraries live on Github, each in its own repository.
$GOPATH is the root of the project - each of your Github repos will be checked out several folders below $GOPATH.Your code layout would look like this:
$GOPATH/
src/
github.com/
jmcvetta/
useless/
.git/
useless.go
useless_test.go
README.md
uselessd/
.git/
uselessd.go
uselessd_test.go
README.mdEach folder under
src/github.com/jmcvetta/ is the root of a separate git checkout.Tha
Code Snippets
bin/
streak # command executable
todo # command executable
pkg/
linux_amd64/
code.google.com/p/goauth2/
oauth.a # package object
github.com/nf/todo/
task.a # package object
src/
code.google.com/p/goauth2/
.hg/ # mercurial repository metadata
oauth/
oauth.go # package source
oauth_test.go # test sourcecamlistore/
cmd/
camget/
main.go
cammount/
main.go
camput/
main.go
camtool/
main.goadder/
adder.go
cmd/
adder/
main.go
adder-server/
main.go$ go get github.com/benbjohnson/adder/...$GOPATH/
src/
github.com/
jmcvetta/
useless/
.git/
useless.go
useless_test.go
README.md
uselessd/
.git/
uselessd.go
uselessd_test.go
README.mdContext
Stack Overflow Q#14867452, score: 148
Revisions (0)
No revisions yet.