How to write Go Code #beginner



This document demonstrates the development of a simple Go package and introduces thego tool, the standard way to fetch, build, and install Go packages and commands.

The gotool requires you to organize your code in a specific way. Please read this document carefully. It explains the simplest way to get up and running with your Go installation.

A similar explanation is available as a screencast.

Code organization Workspaces

The gotool is designed to work with open source code maintained in public repositories. Although you don't need to publish your code, the model for how the environment is set up works the same whether you do or not.

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 gotool builds source packages and installs the resulting binaries to the pkgand bindirectories.

The srcsubdirectory typically contains multiple version control repositories (such as for Git or Mercurial) that track the development of one or more source packages.

To give you an idea of how a workspace looks in practice, here's an example:

bin/hello # command executableoutyet # command executablepkg/linux_amd64/ # package objectsrc/ # Git repository metadatahello/hello.go # command sourceoutyet/main.go# command sourcemain_test.go # test sourcestringutil/reverse.go # package sourcereverse_test.go# test source

This workspace contains one repository ( example) comprising two commands ( helloand outyet) and one library ( stringutil).

A typical workspace would contain many source repositories containing many packages and commands. Most Go programmers keep alltheir Go source code and dependencies in a single workspace.

Commands and libraries are built from different kinds of source packages. We will discuss the distinctionlater.

The GOPATHenvironment variable

The GOPATHenvironment variable specifies the location of your workspace. It is likely the only environment variable you'll need to set when developing Go code.

To get started, create a workspace directory and set GOPATHaccordingly. Your workspace can be located wherever you like, but we'll use $HOME/workin this document. Note that this must notbe the same path as your Go installation. (Another common setup is to set GOPATH=$HOME.)

$ mkdir $HOME/work$ export GOPATH=$HOME/work

For convenience, add the workspace's binsubdirectory to your PATH:

$ export PATH=$PATH:$GOPATH/bin

To learn more about setting up the GOPATHenvironment variable, please see go help gopath

Package paths

The packages from the standard library are given short paths such as "fmt"and "net/http". For your own packages, you must choose a base path that is unlikely to collide with future additions to the standard library or other external libraries.

If you keep your code in a source repository somewhere, then you should use the root of that source repository as your base path. For instance, if you have a GitHubaccount at, that should be your base path.

Note that you don't need to publish your code to a remote repository before you can build it. It's just a good habit to organize your code as if you will publish it someday. In practice you can choose any arbitrary path name, as long as it is unique to the standard library and greater Go ecosystem.

We'll use our base path. Create a directory inside your workspace in which to keep source code:

$ mkdir -p $GOPATH/src/ Your first program

To compile and run a simple program, first choose a package path (we'll use and create a corresponding package directory inside your workspace:

$ mkdir $GOPATH/src/

Next, create a file named hello.goinside that directory, containing the following Go code.

package mainimport "fmt"func main() {fmt.Printf("Hello, world./n")}

Now you can build and install that program with the gotool:

$ go install

Note that you can run this command from anywhere on your system. The gotool finds the source code by looking for the inside the workspace specified by GOPATH.

You can also omit the package path if you run go installfrom the package directory:

$ cd $GOPATH/src/$ go install

This command builds the hellocommand, producing an executable binary. It then installs that binary to the workspace's bindirectory as hello(or, under Windows, hello.exe). In our example, that will be $GOPATH/bin/hello, which is $HOME/work/bin/hello.

The gotool will only print output when an error occurs, so if these commands produce no output they have executed successfully.

You can now run the program by typing its full path at the command line:

$ $GOPATH/bin/helloHello, world.

Or, as you have added $GOPATH/binto your PATH, just type the binary name:

$ helloHello, world.

If you're using a source control system, now would be a good time to initialize a repository, add the files, and commit your first change. Again, this step is optional: you do not need to use source control to write Go code.

$ cd $GOPATH/src/$ git initInitialized empty Git repository in /home/user/work/src/$ git add hello.go$ git commit -m "initial commit"[master (root-commit) 0b4507d] initial commit 1 file changed, 1 insertion(+) create mode 100644 hello.go

Pushing the code to a remote repository is left as an exercise for the reader.

Your first library

Let's write a library and use it from the helloprogram.

Again, the first step is to choose a package path (we'll use and create the package directory:

$ mkdir $GOPATH/src/

Next, create a file named reverse.goin that directory with the following contents.

// Package stringutil contains utility functions for working with strings.package stringutil// Reverse returns its argument string reversed rune-wise left to right.func Reverse(s string) string {r := []rune(s)for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {r[i], r[j] = r[j], r[i]}return string(r)}

Now, test that the package compiles with go build:

$ go build

Or, if you are working in the package's source directory, just:

$ go build

This won't produce an output file. To do that, you must use go install, which places the package object inside the pkgdirectory of the workspace.

After confirming that the stringutilpackage builds, modify your original hello.go(which is in $GOPATH/src/ to use it:

package mainimport ("fmt""")func main() {fmt.Printf(stringutil.Reverse("!oG ,olleH"))}

Whenever the gotool installs a package or binary, it also installs whatever dependencies it has. So when you install the helloprogram

$ go install

the stringutilpackage will be installed as well, automatically.

Running the new version of the program, you should see a new, reversed message:

$ helloHello, Go!

After the steps above, your workspace should look like this:

bin/hello # command executablepkg/linux_amd64/ # this will reflect your OS and # package objectsrc/ # command sourcestringutil/reverse.go# package source

Note that go installplaced the stringutil.aobject in a directory inside pkg/linux_amd64that mirrors its source directory. This is so that future invocations of the gotool can find the package object and avoid recompiling the package unnecessarily. The linux_amd64part is there to aid in cross-compilation, and will reflect the operating system and architecture of your system.

Go command executables are statically linked; the package objects need not be present to run Go programs.

Package names

The first statement in a Go source file must be

package name

where nameis the package's default name for imports. (All files in a package must use the same name.)

Go's convention is that the package name is the last element of the import path: the package imported as " crypto/rot13" should be named rot13.

Executable commands must always use package main.

There is no requirement that package names be unique across all packages linked into a single binary, only that the import paths (their full file names) be unique.

SeeEffective Go to learn more about Go's naming conventions.


Go has a lightweight test framework composed of the go testcommand and the testingpackage.

You write a test by creating a file with a name ending in _test.gothat contains functions named TestXXXwith signature func (t *testing.T). The test framework runs each such function; if the function calls a failure function such as t.Erroror t.Fail, the test is considered to have failed.

Add a test to the stringutilpackage by creating the file $GOPATH/src/ the following Go code.

package stringutilimport "testing"func TestReverse(t *testing.T) {cases := []struct {in, want string}{{"Hello, world", "dlrow ,olleH"},{"Hello, 世界", "界世 ,olleH"},{"", ""},}for _, c := range cases {got := Reverse( got != c.want {t.Errorf("Reverse(%q) == %q, want %q",, got, c.want)}}}

Then run the test with go test:

$ go test 0.165s

As always, if you are running the gotool from the package directory, you can omit the package path:

$ go testok 0.165s

Run go help testand see the testing package documentationfor more detail.

Remote packages

An import path can describe how to obtain the package source code using a revision control system such as Git or Mercurial. The gotool uses this property to automatically fetch packages from remote repositories. For instance, the examples described in this document are also kept in a Git repository hosted at GitHub If you include the repository URL in the package's import path, go getwill fetch, build, and install it automatically:

$ go get$ $GOPATH/bin/helloHello, Go examples!

If the specified package is not present in a workspace, go getwill place it inside the first workspace specified by GOPATH. (If the package does already exist, go getskips the remote fetch and behaves the same as go install.)

After issuing the above go getcommand, the workspace directory tree should now look like this:

bin/hello # command executablepkg/linux_amd64/ package package objectsrc/ # Git repository metadatahello/hello.go# command sourcestringutil/reverse.go # package sourcereverse_test.go # test command sourcestringutil/reverse.go # package sourcereverse_test.go # test source

The hellocommand hosted at GitHub depends on the stringutilpackage within the same repository. The imports in hello.gofile use the same import path convention, so the go getcommand is able to locate and install the dependent package, too.

import ""

This convention is the easiest way to make your Go packages available for others to use. TheGo Wiki and godoc.orgprovide lists of external Go projects.

For more information on using remote repositories with the gotool, see go help importpath.

What's next

Subscribe to the golang-announcemailing list to be notified when a new stable version of Go is released.

SeeEffective Go for tips on writing clear, idiomatic Go code.

TakeA Tour of Go to learn the language proper.

Visit thedocumentation page for a set of in-depth articles about the Go language and its libraries and tools.

Getting help

For real-time help, ask the helpful gophers in #go-nutson the FreenodeIRC server.

The official mailing list for discussion of the Go language is Go Nuts.

Report bugs using theGo issue tracker.