1
0
mirror of https://github.com/golang/go synced 2024-11-24 21:00:09 -07:00
go/doc/code.html
Andrew Gerrand d9b82baac1 doc: update "How to Write Go Code" to use the go tool
R=golang-dev, r, kevlar, rsc
CC=golang-dev
https://golang.org/cl/5534045
2012-01-12 08:25:49 +11:00

342 lines
9.4 KiB
HTML

<!-- How to Write Go Code -->
<h2 id="Introduction">Introduction</h2>
<p>
This document explains how to write a new package
and how to test code.
It assumes you have installed Go using the
<a href="install.html">installation instructions</a>.
</p>
<p>
Before embarking on a change to an existing
package or the creation of a new package,
be sure to send mail to the
<a href="http://groups.google.com/group/golang-nuts">mailing list</a>
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.
</p>
<h2 id="Community_resources">Community resources</h2>
<p>
For real-time help, there may be users or developers on
<code>#go-nuts</code> on the <a href="http://freenode.net/">Freenode</a> IRC server.
</p>
<p>
The official mailing list for discussion of the Go language is
<a href="http://groups.google.com/group/golang-nuts">Go Nuts</a>.
</p>
<p>
Bugs can be reported using the <a href="http://code.google.com/p/go/issues/list">Go issue tracker</a>.
</p>
<p>
For those who wish to keep up with development,
there is another mailing list, <a href="http://groups.google.com/group/golang-checkins">golang-checkins</a>,
that receives a message summarizing each checkin to the Go repository.
</p>
<h2 id="New_package">Creating a new package</h2>
<h3>Choosing an import path</h3>
<p>
The standard packages are given short names like <code>fmt</code> and
<code>net/http</code> 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.
</p>
<p>
For instance, if your source repository is at <code>example.com</code>
or <code>code.google.com/p/example</code>, you should begin your package
paths with that URL, as in "<code>example.com/foo/bar</code>" or
"<code>code.google.com/p/example/foo/bar</code>".
This way the <a href="/cmd/go/"><code>go</code> tool</a> can automatically
check out and build the source code from its import path.
</p>
<p>
If you don't intend your code to be installed in this way, you should at
least use a unique prefix like "<code>widgets/</code>", as in
"<code>widgets/foo/bar</code>". 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.
</p>
<h3>The <code>go</code> tool and <code>GOPATH</code></h3>
<p>
The <a href="/cmd/go/"><code>go</code> tool</a> 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.
</p>
<p>
To use the <code>go</code> tool effectively you must set the
<code>GOPATH</code> variable.
<code>GOPATH</code> specifies a list of paths that contain Go source code
and package binaries. Source code, package objects, and command binaries are
located inside the <code>GOPATH</code>s' <code>src</code>, <code>pkg</code>,
and <code>bin</code> subdirectories respectively.
</p>
<p>
You should set <code>GOPATH</code> in your shell profile
(<code>$HOME/.bashrc</code>, <code>$HOME/.profile</code>, or equivalent).
</p>
<p>
This shell session demonstrates setting <code>GOPATH</code>, creating a trivial
<code>widgets/foo</code> package, and building and installing the package.
</p>
<pre>
$ export GOPATH=$HOME/gocode
$ mkdir -p $GOPATH/src/widgets/foo
$ cat &gt; $GOPATH/src/widgets/foo/foo.go
package foo
const String = "Go rules!"
^D
$ go install widgets/foo
$ ls $GOPATH/pkg/*/example
foo.a
</pre>
<p>(<code>^D</code> means to type Control-D.)</p>
<p>
Type <code>go help gopath</code> on the command line for more information
about <code>GOPATH</code>.
</p>
<h3>Go source files</h3>
<p>
The first statement in a Go source file should be <code>package
<i>name</i></code>, where <code><i>name</i></code> is the package's default
name for imports.
(All files in a package must use the same <code><i>name</i></code>.)
Go's convention is that the package name is the last element of the
import path: the package imported as "<code>crypto/rot13</code>"
should be named <code>rot13</code>.
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.
</p>
<p>
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.
</p>
<p>
Writing clean, idiomatic Go code is beyond the scope of this document.
<a href="effective_go.html">Effective Go</a> is an introduction to
that topic.
</p>
<h2 id="Building_programs">Building programs</h2>
<p>
The <a href="/cmd/go/"><code>go</code> tool</a> treats code belonging to
<code>package main</code> as an executable command, and installs the package
binary to the <code>GOPATH</code>'s <code>bin</code> subdirectory.
</p>
<p>
Building executable commands is the same as building packages.
Use "<code>go install</code>":
</p>
<pre>
$ cat &gt; $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!
</pre>
<p>
Run <code>go help build</code> and <code>go help install</code> for more
about building and installing Go binaries.
</p>
<h2 id="Testing">Testing</h2>
<p>
Go has a lightweight test framework composed of the <code>go</code> tool and
the <code>testing</code> package.
You write a test by creating a file with a name ending in <code>_test.go</code>
that contains functions named <code>TestXXX</code> with signature
<code>func (t *testing.T)</code>.
The test framework runs each such function;
if the function calls a failure function such as <code>t.Error</code> or
<code>t.Fail</code>, the test is considered to have failed.
Run <code>go help test</code> and see the
<a href="/pkg/testing/">testing package documentation</a> for more detail.
</p>
<p>
To run the test, run "<code>go test</code>":
</p>
<pre>
$ cat &gt; $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
</pre>
<p>
If your change affects performance, add a <code>Benchmark</code> function
(run <code>go help testfunc</code>) and run it using <code>go test
-test.bench=.*</code>.
</p>
<h2 id="pkg_example">An example package with tests</h2>
<p>
This example package, <code>numbers</code>, consists of the function
<code>Double</code>, which takes an <code>int</code> and returns that value
multiplied by 2. It consists of two files.
</p>
<p>
First, the package implementation, <code>numbers.go</code>:
</p>
<pre>
package numbers
func Double(i int) int {
return i * 2
}
</pre>
<p>
Next, the tests, <code>numbers_test.go</code>:
</p>
<pre>
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)
}
}
}
</pre>
<p>
Running <code>go install</code> will build and install the package to
the <code>GOPATH</code>'s <code>pkg</code> directory
(it can then be imported by any other Go program).
</p>
<p>
Running <code>go test</code> will rebuild the package, including the
<code>numbers_test.go</code> file, and then run the <code>TestDouble</code>
function. The output "<code>ok</code>" indicates that all tests passed
successfully. Breaking the implementation by changing the multiplier from
<code>2</code> to <code>3</code> will allow you to see how failing tests are
reported.
</p>
<p>
Run <code>go help test</code>, <code>go help testfunc</code>,
and <code>go help testflag</code> and see the
<a href="/pkg/testing/">testing package documentation</a> for more detail.
</p>
<h2 id="arch_os_specific">Architecture- and operating system-specific code</h2>
<p>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.</p>
<p>To compile such code, use the <code>$GOOS</code> and <code>$GOARCH</code>
<a href="/doc/install.html#environment">environment variables</a> in your
source file names.</p>
<p>For example, consider the package <code>foo</code> that consists of four
files:</p>
<pre>
foo.go
foo_386.go
foo_amd64.go
foo_arm.go
</pre>
describes a package that builds on
different operating systems by parameterizing the file name with
<code>$GOOS</code>.</p>
<p>The general code goes in <code>foo.go</code>, while architecture-specific
code goes in <code>foo_386.go</code>, <code>foo_amd64.go</code>, and
<code>foo_arm.go</code>.</p>
<p>If you follow these conventional parameterizations, tools such as the <a
href="/cmd/go/"><code>go</code> tool</a> will work seamlessly with your
package:</p>
<pre>
foo_$GOOS.go
foo_$GOARCH.go
foo_$GOOS_$GOARCH.go
</pre>
<p>The same holds for <code>.s</code> (assembly) and <code>.c</code> files.</p>