Organizing Go code

David Crawshaw
crawshaw@golang.org


* Packages

* Go programs are made up of packages

All Go source is part of a package.
Every file begins with a package statement.
Programs start in package main.

.play organizeio/hello.go

For very small programs, `main` is the only package you need to write.

The hello world program _imports_ package `fmt`.

The function `Println` is defined in the fmt package.

* An example package: fmt

	// Package fmt implements formatted I/O.
	package fmt

	// Println formats using the default formats for its
	// operands and writes to standard output.
	func Println(a ...interface{}) (n int, err error) {
		...
	}

	func newPrinter() *pp {
		...
	}

The `Println` function is _exported_. It starts with an upper case
letter, which means other packages are allowed to call it.

The `newPrinter` function is _unexported_. It starts with a lower
case letter, so it can only be used inside the fmt package.

* The shape of a package

Packages collect related code.

They can be big or small,
and may be spread across multiple files.

All the files in a package live in a single directory.

The `net/http` package exports more than 100 names. (18 files)
The `errors` package exports just one. (1 file)

* The name of a package

Keep package names short and meaningful.
Don't use underscores, they make package names long.

- `io/ioutil` not `io/util`
- `suffixarray` not `suffix_array`

Don't overgeneralize. A `util` package could be anything.

The name of a package is part of its type and function names.
On its own, type `Buffer` is ambiguous. But users see:

	buf := new(bytes.Buffer)

Choose package names carefully.

Choose good names for users.

* The testing of a package

Tests are distinguished by file name. Test files end in `_test.go`.

	package fmt

	import "testing"

	var fmtTests = []fmtTest{
		{"%d", 12345, "12345"},
		{"%v", 12345, "12345"},
		{"%t", true, "true"},
	}

	func TestSprintf(t *testing.T) {
		for _, tt := range fmtTests {
			if s := Sprintf(tt.fmt, tt.val); s != tt.out {
				t.Errorf("...")
			}
		}
	}

Test well.

* Code organization

* Introducing workspaces

Your Go code is kept in a _workspace_.

A workspace contains _many_ source repositories (git, hg).

The Go tool understands the layout of a workspace.
You don't need a `Makefile`. The file layout is everything.

Change the file layout, change the build.

	$GOPATH/
		src/
			github.com/user/repo/
				mypkg/
					mysrc1.go
					mysrc2.go
				cmd/mycmd/
					main.go
		bin/
			mycmd


* Let's make a workspace

	mkdir /tmp/gows
	GOPATH=/tmp/gows

The `GOPATH` environment variable tells the Go tool where your workspace is located.

	go get github.com/dsymonds/fixhub/cmd/fixhub

The `go` `get` command fetches source repositories from the internet and places them in your workspace.

Package paths matter to the Go tool. Using "github.com/..."
means the tool knows how to fetch your repository.

	go install github.com/dsymonds/fixhub/cmd/fixhub

The go install command builds a binary and places it in `$GOPATH/bin/fixhub`.

* Our workspace

	$GOPATH/
		bin/fixhub                              # installed binary
		pkg/darwin_amd64/                       # compiled archives
			code.google.com/p/goauth2/oauth.a
			github.com/...
		src/                                    # source repositories
			code.google.com/p/goauth2/
				.hg
				oauth                           # used by package go-github
				...
			github.com/
				golang/lint/...                 # used by package fixhub
					.git
				google/go-github/...            # used by package fixhub
					.git
				dsymonds/fixhub/
					.git
					client.go
					cmd/fixhub/fixhub.go        # package main

`go` `get` fetched many repositories.
`go` `install` built a binary out of them.


* Why prescribe file layout?

Using file layout for builds means less configuration.
In fact, it means no configuration.
No `Makefile`, no `build.xml`.

Less time configuring means more time programming.

Everyone in the community uses the same layout.
This makes it easier to share code.

The Go tool helps build the Go community.

* Where's your workspace?

It is possible to have multiple workspaces, but most people just use one.

So where do you point your `GOPATH`? A common preference:

.image organizeio/home.png

This puts `src`, `bin`, and `pkg` directories in your home directory.

(Convenient, because `$HOME/bin` is probably already in your `PATH`.)


* Working with workspaces

Unix eschews typing:

	CDPATH=$GOPATH/src/github.com:$GOPATH/src/code.google.com/p

	$ cd dsymonds/fixhub
	/tmp/gows/src/github.com/dsymonds/fixhub
	$ cd goauth2
	/tmp/gows/src/code.google.com/p/goauth2
	$

A shell function for your `~/.profile`:

	gocd () { cd `go list -f '{{.Dir}}' $1` }

This lets you move around using the Go tool's path names:

	$ gocd .../lint
	/tmp/gows/src/github.com/golang/lint
	$


* The Go tool's many talents

	$ go help
	Go is a tool for managing Go source code.

	Usage:

		go command [arguments]

	The commands are:

Worth exploring! Some highlights:

	    build       compile packages and dependencies
	    get         download and install packages and dependencies
	    install     compile and install packages and dependencies
	    test        test packages

There are more useful subcommands. Check out `vet` and `fmt`.

* Dependency management

* In production, versions matter.

`go` `get` always fetches the latest code, even if your build breaks.

.image organizeio/gogetversion.png

That's fine when developing. It's not fine when releasing.
We need other tools.

* Versioning

My favorite technique: vendoring.

For building binaries, import the packages you care about
into a `_vendor` workspace.

	GOPATH=/tmp/gows/_vendor:/tmp/gows

For building libraries, import the packages you care about
into your repository. Rename the imports to:

	import "github.com/you/proj/vendor/github.com/them/lib"

Long paths, but trivial to automate. Write a Go program!

Another technique: [[http://gopkg.in][gopkg.in]], provides versioned package paths:

	gopkg.in/user/pkg.v3 -> github.com/user/pkg (branch/tag v3, v3.N, or v.3.N.M)

* Naming

* Names matter

Programs are full of names. Names have costs and benefits.

*Costs*: *space* *and* *time*
Names need to be in short term memory when reading code.
You can only fit so many. Longer names take up more space.

*Benefits:* *information*
A good name is not only a referent, it conveys information.

Use the shortest name that carries the right amount of information in its context.

Devote time to naming.

* Name style

Use `camelCase`, `not_underscores`.
Local variable names should be short, typically one or two characters.

Package names are usually one lowercase word.

Global variables should have longer names.

Don't stutter.

- `bytes.Buffer` not `bytes.ByteBuffer`
- `zip.Reader` not `zip.ZipReader`
- `errors.New` not `errors.NewError`
- `r` not `bytesReader`
- `i` not `loopIterator`

* Doc comments

Doc comments precede the declaration of an exported identifier:

        // Join concatenates the elements of elem to create a single string.
        // The separator string sep is placed between elements in the resulting string.
        func Join(elem []string, sep string) string {

The godoc tool extracts such comments and presents them on the web:

.image organizeio/godoc.png

* Writing doc comments

Doc comments should be English sentences and paragraphs.
They use no special formatting beyond indentation for preformatted text.

Doc comments should begin with the noun they describe.

	// Join concatenates… 		good
	// This function… 			bad

Package docs go above the package declaration:

	// Package fmt…
	package fmt

Read the world's Go docs on [[godoc.org]]. E.g.

[[http://godoc.org/code.google.com/p/go.tools/cmd/vet]]

* Questions?
