Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

Next Steps in Go: Code Organization

My first steps in learning Go were simple “scripts”; programs compiled and immediately executed by the go command-line tool. This was a great way to quickly get started; kind of similar to using a REPL. However, I soon wanted to learn how to structure larger programs, create reusable libraries, and use third-party code. In this post, we’ll look at how Go code is organized into packages, the various commands to build and install them, and how to integrate third-party libraries.


All Go programs and libraries are defined in packages. Packages are named after the final part in their directory path. An import declaration is used to load a package.

package main

import (

func main() {
  resp, err := http.Get("")
  if err != nil {

  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {

The entry point for every Go program is the main function in the main package. This program imports three packages from the Go standard library. A package’s name is used to access its exported interface. In this example, http is used to access the package’s Get function.

Creating a Custom Package

The first step in creating a custom package is to create a workspace. A workspace is a directory hierarchy containing three subdirectories:

  • src – Go source code organized into packages
  • pkg – OS and architecture specific compilation artifacts
  • bin – executable Go programs

When you import a custom package, Go looks for its definition in each workspace listed in the GOPATH environment variable.

Let’s create a workspace and set the GOPATH.

% mkdir -p ~/Projects/golang/src

% export GOPATH=~/Projects/golang/

Our custom package will be defined in a src subdirectory.


package foo

import (

func Bar() {

% tree golang
└── src
    └── foo
        └── foo.go

A Go package is named after its directory. Within its directory, it can be implemented in any number of arbitrarily named files. In this example, I chose to name our custom package’s only file after the package.

Importing a Custom Package

With this directory structure in place and the GOPATH set, we can now create a Go program that can import and use our custom package. This program will also be defined in a src subdirectory.


package main

import (

func main() {

% tree golang
└── src
    ├── foo
    │   └── foo.go
    └── fooer
        └── fooer.go

Our next step is to build and install this program.

Building Go Code

Build Go code using the go command-line tool’s build command.

Building a program creates an executable file in the program’s directory. The executable file is named after its directory.

% pwd

% go build

% ls
fooer fooer.go

% ./fooer

Building a custom package results in no build artifacts.

Installing Go Code

Install Go code using the go command-line tool’s install command.

Programs are installed in the workspace’s bin directory.

% pwd

% go install

% ls ../../bin

Custom packages are installed in an OS and architecture specific subdirectory in the workspace’s pkg directory.

% pwd

% go install

% ls ../../pkg/darwin_amd64

Add $GOPATH/bin to your PATH to make executing Go programs easier.

Integrating Third-Party Go Code

Integrate third-party Go code using the go command-line tool’s get command. Third-party code is downloaded and installed in the first workspace listed in the GOPATH.

% pwd

% go get -v (download)

% ls foo           fooer

% ls ../pkg/darwin_amd64/ foo.a

Moving Beyond Scripts

Every programming language has its own way of organizing code. Knowing where a language is expecting code is a must when moving beyond simple scripts.

  1. Ross says:

    Great post Jared, I’ve really been enjoying your series on Go! Quick question on code organization of multiple projects on the same machine:

    Do you create multiple workspaces (ie, one per project) -OR- a single workspace with a single src, pkg, bin directory tree for all projects?

    To put it another way, should my src directories look like this:


    – OR –


    The IntelliJ IDEA plugin seems to expect the former whereas seems to expect the latter.

    And, imho, the former seems a much nicer way to keep things organized.

  2. Jared Carroll says:


    There doesn’t seem to be a consensus in the Go community on single vs. multiple workspaces. The IntelliJ Go plugin creates a separate directory for each project; so it must append each directory to the GOPATH. The Go docs ( mention multiple workspaces, but then
    provide an example using multiple libraries, each organized in their own Git repository, in a single workspace.

    The single workspace feels like how Unix stores binaries in a few places /bin or /usr/bin for example. The multiple workspace equivalent would require adding more and more custom ‘bin’ directories to your PATH; which feels a little less elegant.

    I guess it comes down to personal/team preference. For a language that eliminated code formatting bikeshedding via `gofmt`, it’s disappointing there’s not a definite advantage to either way.

  3. Ross Hale says:

    Sounds like I’ll be sticking with multiple workspaces for now — despite the pain of GOPATH and package management. Thanks!

  4. Jeff Hui says:

    The preferred way (according to Andrew Gerrand) seems to be using one GOPATH with all the projects in the same workspace.!topic/golang-nuts/dxOFYPpJEXo

    Although, I prefer separate workspaces :(

  5. Gerard says:

    Thanks for this! It really demostrated Golang’s custom package build process in a consise and simple example.

  6. Dagen Brock says:

    I’ve been putting all my GOPATH stuff in a “gorc” file. When I work on a project, I just run its gorc file. I suppose it might be a bit wonky, but I typically do all of my build/run commands from one small terminal in the corner, so I only have to run that once per project/session. I open other terminals to do all of my editing in vi.

    Thanks for the article. I do wish you touched a bit on what level of related functionality *should* go in one package, but I suppose that’s a matter of taste and style, and probably leads to religious arguments. ;)

  7. Tony says:

    Thank you writing this Jared. It worked perfectly!

  8. Yogesh says:

    I have Go project with multiple packages(containing one or more source files) into it.I am using IntelliJ IDEA and able to build the project and run it.

    However, I want to run multiple instances of the resulting binary in a distributed environment. So need a binary executable for the same. How can I generate single binary executable for the entire project?

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *