This document explains how to write a new package and how to test code. It assumes you have installed Go using the installation instructions.
Before embarking on a change to an existing package or the creation of a new package, be sure to send mail to the mailing list to let people know what you are thinking of doing. Doing so helps avoid duplication of effort and enables discussions about design before any code has been written.
For real-time help, there may be users or developers on
#go-nuts
on the Freenode IRC server.
The official mailing list for discussion of the Go language is Go Nuts.
Bugs can be reported using the Go issue tracker.
For those who wish to keep up with development, there is another mailing list, golang-checkins, that receives a message summarizing each checkin to the Go repository.
The standard packages are given short names like fmt
and
net/http
for convenience.
For your own projects, choose a name space that is unlikely
to collide with future additions to the standard library or other
external libraries.
For instance, if your source repository is at example.com
or code.google.com/p/example
, you should begin your package
paths with that URL, as in "example.com/foo/bar
" or
"code.google.com/p/example/foo/bar
".
This way the go
tool can automatically
check out and build the source code from its import path.
If you don't intend your code to be installed in this way, you should at
least use a unique prefix like "widgets/
", as in
"widgets/foo/bar
". A good rule is to use a prefix such as your
company or project name since it is unlikely to be used by another group.
go
tool and GOPATH
The go
tool is the standard means of
building and installing Go libraries and programs. It is a "zero configuration"
tool; it determines how to build Go packages from their source code alone.
To use the go
tool effectively you must set the
GOPATH
variable.
GOPATH
specifies a list of paths that contain Go source code
and package binaries. Source code, package objects, and command binaries are
located inside the GOPATH
s' src
, pkg
,
and bin
subdirectories respectively.
You should set GOPATH
in your shell profile
($HOME/.bashrc
, $HOME/.profile
, or equivalent).
This shell session demonstrates setting GOPATH
, creating a trivial
widgets/foo
package, and building and installing the package.
$ export GOPATH=$HOME/gocode $ mkdir -p $GOPATH/src/widgets/foo $ cat > $GOPATH/src/widgets/foo/foo.go package foo const String = "Go rules!" ^D $ go install widgets/foo $ ls $GOPATH/pkg/*/widgets foo.a
(^D
means to type Control-D.)
Type go help gopath
on the command line for more information
about GOPATH
.
The first statement in a Go source file should be package
name
, where name
is 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
.
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.
Go compiles all the source files in a package at once, so one file can refer to constants, variables, types, and functions in another file without special arrangement or declarations.
Writing clean, idiomatic Go code is beyond the scope of this document. Effective Go is an introduction to that topic.
The go
tool treats code belonging to
package main
as an executable command, and installs the package
binary to the GOPATH
's bin
subdirectory.
Building executable commands is the same as building packages.
Use "go install
":
$ mkdir -p $GOPATH/src/widgets/bar $ cat > $GOPATH/src/widgets/bar/bar.go package main import ( "fmt" "widgets/foo" ) func main() { fmt.Println(foo.String) } ^D $ go install widgets/bar $ $GOPATH/bin/bar Go rules!
Run go help build
and go help install
for more
about building and installing Go binaries.
Go has a lightweight test framework composed of the go
tool and
the testing
package.
You write a test by creating a file with a name ending in _test.go
that contains functions named TestXXX
with signature
func (t *testing.T)
.
The test framework runs each such function;
if the function calls a failure function such as t.Error
or
t.Fail
, the test is considered to have failed.
Run go help test
and see the
testing package documentation for more detail.
To run the test, run "go test
":
$ cat > $GOPATH/src/widgets/foo/foo_test.go package foo import "testing" func TestString(t *testing.T) { const expect = "Go rules!" if String != expect { t.Errorf("String == %q, want %q", String, expect) } } ^D $ go test widgets/foo ok widgets/foo 0.018s
If your change affects performance, add a Benchmark
function
(run go help testfunc
) and run it using go test
-test.bench=.*
.
This example package, numbers
, consists of the function
Double
, which takes an int
and returns that value
multiplied by 2. It consists of two files.
First, the package implementation, numbers.go
:
package numbers func Double(i int) int { return i * 2 }
Next, the tests, numbers_test.go
:
package numbers import ( "testing" ) type doubleTest struct { in, out int } var doubleTests = []doubleTest{ doubleTest{1, 2}, doubleTest{2, 4}, doubleTest{-5, -10}, } func TestDouble(t *testing.T) { for _, dt := range doubleTests { v := Double(dt.in) if v != dt.out { t.Errorf("Double(%d) = %d, want %d.", dt.in, v, dt.out) } } }
Running go install
will build and install the package to
the GOPATH
's pkg
directory
(it can then be imported by any other Go program).
Running go test
will rebuild the package, including the
numbers_test.go
file, and then run the TestDouble
function. The output "ok
" indicates that all tests passed
successfully. Breaking the implementation by changing the multiplier from
2
to 3
will allow you to see how failing tests are
reported.
Run go help test
, go help testfunc
,
and go help testflag
and see the
testing package documentation for more detail.
First, a disclaimer: very few Go packages should need to know about the hardware and operating system they run on. In the vast majority of cases the language and standard library handle most portability issues. This section is a guide for experienced systems programmers who have a good reason to write platform-specific code, such as assembly-language support for fast trigonometric functions or code that implements a common interface above different operating systems.
To compile such code, use the $GOOS
and $GOARCH
environment variables in your
source file names.
For example, consider the package foo
that consists of four
files:
foo.go foo_386.go foo_amd64.go foo_arm.go
describes a package that builds on
different architectures by parameterizing the file name with
$GOARCH
.
The general code goes in foo.go
, while architecture-specific
code goes in foo_386.go
, foo_amd64.go
, and
foo_arm.go
.
If you follow these conventional parameterizations, tools such as the go
tool will work seamlessly with your
package:
foo_$GOOS.go foo_$GOARCH.go foo_$GOOS_$GOARCH.go
The same holds for .s
(assembly) and .c
files.