mirror of
https://github.com/golang/go
synced 2024-11-12 00:20:22 -07:00
f18b0b0c16
R=golang-dev, adg, r CC=golang-dev https://golang.org/cl/5649068
345 lines
9.4 KiB
HTML
345 lines
9.4 KiB
HTML
<!--{
|
|
"Title": "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 > $GOPATH/src/widgets/foo/foo.go
|
|
package foo
|
|
const String = "Go rules!"
|
|
^D
|
|
$ go install widgets/foo
|
|
$ ls $GOPATH/pkg/*/widgets
|
|
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>
|
|
$ 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!
|
|
</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 > $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
|
|
</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 architectures by parameterizing the file name with
|
|
<code>$GOARCH</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>
|