Folder structure

Go projects are composed by packages. We call commands the packages that have the main identifier.

A project can have

  • 1 package
  • n packages
  • 1 command
  • 1 command and 1 package
  • n commands and 1 package
  • 1 command and n packages
  • n commands and n packages

Depending on the nature of your project you need to organize the folder structure in a certain way.

Some real world examples

Let’s see some real world examples of this in the wild, here below. I took them from Five suggestions for setting up a Go project by Dave Cheney.

Example of a project with 1 package:

Example of a project with n packages

Example of a project with 1 command

Example of a project with 1 command and 1 package

Example of a project with n commands and n packages

Conventions for file structure inside a project

From those examples we can tell these conventions:

If you have one command, it can live in a main.go file in the root of the project.

With more than one command, create a cmd/ folder, and under this, create a folder with the name of the command. In each folder, ideally a .go file with the same name will contain the main() function, although it’s not mandatory.

Packages go in their own folder, unless you just have one package.

Filesystem location for installed packages

Any Go project can be installed by using go get. go get will install packages under $GOPATH/src. For example typing

go get

will download and install the 1-package repo located at, and it will put it under $GOPATH/src/ We can just reference it in our programs using import

What if we type

go get

instead? Remember, this is the one-command repository we listed before.

go get will download it like it did for, and put it under $GOPATH/src, BUT since it’s a command, it will also compile and create a $GOPATH/bin/godep binary.

Go commands are compiled to the name of the enclosing folder, in this case the folder was the root one, so it’s godep. In the case of multiple commands, it will take the last subfolder name. E.g. an ideal would be compiled to unzip. It does not take the name of the file containing the main() function.


Go has a quite unique concept of workspace. A workspace is the folder structure that $GOPATH points to. When you create a new workspace, add the $GOPATH/bin folder to your path as well. For example if you want to set your workspace to ~/go (which by the ways is the default):

export GOPATH=~/go
export PATH=~/go/bin:$PATH

Now, any Go code you run will reference this folder. This allows you to create separate workspaces, although as stated in the official docs,

Go programmers typically keep all their Go code in a single workspace.

Note that this differs from other programming environments in which every project has a separate workspace and workspaces are closely tied to version control repositories.

This is an example of a workspace, listed in the official docs:

    hello                          # command executable
    outyet                         # command executable
            stringutil.a           # package object
        .git/                      # Git repository metadata
        hello.go               # command source
        main.go                # command source
        main_test.go           # test source
        reverse.go             # package source
        reverse_test.go        # test source
        .git/                  # Git repository metadata
        reader.go              # package source
        writer.go              # package source
    #... (many more repositories and packages omitted) ...

Knowing this, let’s see..

Where to place your commands and packages

When running commands using go run, you can have your project anywhere you like, but this is an approach useful only for quick testing.

You should create your programs inside the $GOPATH/src folder, with your unique namespace, e.g.


When running (from anywhere in the system)

go install

Go will compile and put the hello binary in $GOPATH/bin, ready to be run from anywhere in the system.

The same goes for packages, except that when running go install, it will put the compiled package under $GOPATH/pkg.