Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a sensible way to layout a Go project [closed]

Tags:

go

project

People also ask

Where do you put go projects?

The GOPATH environment variableIt defaults to a directory named go inside your home directory, so $HOME/go on Unix, $home/go on Plan 9, and %USERPROFILE%\go (usually C:\Users\YourName\go ) on Windows. If you would like to work in a different location, you will need to set GOPATH to the path to that directory.


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:

  • src contains Go source files organized into packages (one package per directory),
  • pkg contains package objects, and
  • bin contains 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 source

Update 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.go

Library 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.go

Users 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.

  1. 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.
  2. Organize the most important type at the top of the file and add types in decreasing importance towards the bottom of the file.
  3. 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.md

Each folder under src/github.com/jmcvetta/ is the root of a separate git checkout.

That attracted some criticisms though, in this reddit page:

I highly recommend not structuring the repo the way you have, it'll break "go get", which is one of the most useful things about Go.
It's far better to write your code for people who do know Go, since they're most likely to be the ones compiling it.
And for people who don't, they'll at least get a feel for the language.

Put the main package in the root of the repo.
Have the assets in a subdirectory (to keep things neat).
Keep the meat of the code in a subpackage (in case anyone wants to reuse it outside your binary).
Include a setup script in the root of the repo so it's easy to find.

It's still only a two step process to download, build, install, and setup.:

  • "go get <your repo path>": downloads and installs the go code, with a subdir for the assets
  • $GOPATH/<your repo path>/setup.sh: distributes the assets to the right place and installs the service

I assume that with 'project' you don't mean a Go package but a software you develop. Otherwise you can get help here and here. However it's not so much different to writing packages for Go: Use packages, create a folder for each package and combine those packages in your application.

To build yourself an opinion, you can look at trending Go repositories on github: https://github.com/trending/go. Notable examples are cayley and zeus.

The most popular scheme is probably to have a main Go file and many modules and submodules in their own directories. In case you have many meta files (doc, license, templates, ...) you may want to put the source code into a subdirectory. That's what I did so far.


There is a recommended approach from the authors of Golang that defines how to layout your code to work best with the go tools and to support source control systems


You should probably also have a look into this repo. It shows a lot of ideas how to structure go applications: https://github.com/golang-standards/project-layout