1
0
mirror of https://github.com/golang/go synced 2024-11-12 07:40:23 -07:00
go/doc/code.html
2011-03-04 16:28:27 +11:00

369 lines
10 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>
<p>
The source code for the package with import path
<code>x/y</code> is, by convention, kept in the
directory <code>$GOROOT/src/pkg/x/y</code>.
</p>
<h3>Makefile</h3>
<p>
It would be nice to have Go-specific tools that
inspect the source files to determine what to build and in
what order, but for now, Go uses GNU <code>make</code>.
Thus, the first file to create in a new package directory is
usually the <code>Makefile</code>.
The basic form used in the Go source tree
is illustrated by <a href="../src/pkg/container/vector/Makefile"><code>src/pkg/container/vector/Makefile</code></a>:
</p>
<pre>
include ../../../Make.inc
TARG=container/vector
GOFILES=\
intvector.go\
stringvector.go\
vector.go\
include ../../../Make.pkg
</pre>
<p>
Outside the Go source tree (for personal packages), the standard form is
</p>
<pre>
include $(GOROOT)/src/Make.inc
TARG=mypackage
GOFILES=\
my1.go\
my2.go\
include $(GOROOT)/src/Make.pkg
</pre>
<p>
The first and last lines <code>include</code> standard definitions and rules.
Packages maintained in the standard Go tree use a relative path (instead of
<code>$(GOROOT)/src</code>) so that <code>make</code> will work correctly
even if <code>$(GOROOT)</code> contains spaces.
This makes it easy for programmers to try Go.
</p>
<p>
If you have not set <code>$GOROOT</code> in your environment,
you must run <code>gomake</code> to use this form of makefile.
<code>Gomake</code> also takes care to invoke GNU Make
even on systems where it is installed as <code>gmake</code>
rather than <code>make</code>.
</p>
<p>
<code>TARG</code> is the target install path for the package,
the string that clients will use to import it.
Inside the Go tree, this string should be the same as the directory
in which the <code>Makefile</code> appears, with the
<code>$GOROOT/src/pkg/</code> prefix removed.
Outside the Go tree, you can use any <code>TARG</code> you
want that doesn't conflict with the standard Go package names.
A common convention is to use an identifying top-level name
to group your packages: <code>myname/tree</code>, <code>myname/filter</code>, etc.
Note that even if you keep your package source outside the
Go tree, running <code>make install</code> installs your
package binaries in the standard location&mdash;<code>$GOROOT/pkg</code>&mdash;to
make it easy to find them.
</p>
<p>
<code>GOFILES</code> is a list of source files to compile to
create the package. The trailing <code>\</code> characters
allow the list to be split onto multiple lines
for easy sorting.
</p>
<p>
If you create a new package directory in the Go tree, add it to the list in
<code>$GOROOT/src/pkg/Makefile</code> so that it
is included in the standard build. Then run:
<pre>
cd $GOROOT/src/pkg
./deps.bash
</pre>
<p>
to update the dependency file <code>Make.deps</code>.
(This happens automatically each time you run <code>all.bash</code>
or <code>make.bash</code>.)
</p>
<p>
If you change the imports of an existing package,
you do not need to edit <code>$GOROOT/src/pkg/Makefile</code>
but you will still need to run <code>deps.bash</code> as above.
</p>
<h3>Go source files</h3>
<p>
The first statement in each of the source files listed in the <code>Makefile</code>
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>To build a Go program with gomake, create a Makefile alongside your program's
source files. It should be similar to the example above, but include
<code>Make.cmd</code> instead of <code>Make.pkg</code>:
<pre>
include $(GOROOT)/src/Make.inc
TARG=helloworld
GOFILES=\
helloworld.go\
include $(GOROOT)/src/Make.cmd
</pre>
<p>Running <code>gomake</code> will compile <code>helloworld.go</code>
and produce an executable named <code>helloworld</code> in the current
directory.
</p>
<p>
Running <code>gomake install</code> will build <code>helloworld</code> if
necessary and copy it to the <code>$GOBIN</code> directory
(<code>$GOROOT/bin/</code> is the default).
</p>
<h2 id="Testing">Testing</h2>
<p>
Go has a lightweight test framework known as <code>gotest</code>.
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.
The <a href="/cmd/gotest/">gotest command documentation</a>
and the <a href="/pkg/testing/">testing package documentation</a> give more detail.
</p>
<p>
The <code>*_test.go</code> files should not be listed in the <code>Makefile</code>.
</p>
<p>
To run the test, run either <code>make test</code> or <code>gotest</code>
(they are equivalent).
To run only the tests in a single test file, for instance <code>one_test.go</code>,
run <code>gotest one_test.go</code>.
</p>
<p>
If your change affects performance, add a <code>Benchmark</code> function
(see the <a href="/cmd/gotest/">gotest command documentation</a>)
and run it using <code>gotest -test.bench=.</code>.
</p>
<p>
Once your new code is tested and working,
it's time to get it <a href="contribute.html">reviewed and submitted</a>.
</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 three 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>
Finally, the <code>Makefile</code>:
</p>
<pre>
include $(GOROOT)/src/Make.inc
TARG=numbers
GOFILES=\
numbers.go\
include $(GOROOT)/src/Make.pkg
</pre>
<p>
Running <code>gomake install</code> will build and install the package to
the <code>$GOROOT/pkg/</code> directory (it can then be used by any
program on the system).
</p>
<p>
Running <code>gomake test</code> (or just running the command
<code>gotest</code>) will rebuild the package, including the
<code>numbers_test.go</code> file, and then run the <code>TestDouble</code>
function. The output "<code>PASS</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>
See the <a href="/cmd/gotest/">gotest documentation</a> and the
<a href="/pkg/testing/">testing package</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 and <code>Makefile</code>.</p>
<p>For example, this <code>Makefile</code> describes a package that builds on
different operating systems by parameterizing the file name with
<code>$GOOS</code>.</p>
<pre>
include $(GOROOT)/src/Make.inc
TARG=mypackage
GOFILES=\
my.go\
my_$(GOOS).go\
include $(GOROOT)/src/Make.pkg
</pre>
<p>The OS-specific code goes in <code>my_linux.go</code>,
<code>my_darwin.go</code>, and so on.</p>
<p>If you follow these conventional parameterizations, tools such as
<a href="/cmd/goinstall/">goinstall</a> will work seamlessly with your package:
</p>
<pre>
my_$(GOOS).go
my_$(GOARCH).go
my_$(GOOS)_$(GOARCH).go
</pre>
<p>The same holds for <code>.s</code> (assembly) files.</p>