1
0
mirror of https://github.com/golang/go synced 2024-11-13 17:00:22 -07:00

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
This commit is contained in:
Andrew Gerrand 2012-01-12 08:25:49 +11:00
parent 014c342b1e
commit d9b82baac1

View File

@ -45,120 +45,89 @@ that receives a message summarizing each checkin to the Go repository.
<h2 id="New_package">Creating a new package</h2> <h2 id="New_package">Creating a new package</h2>
<h3>Choosing an import path</h3>
<p> <p>
The source code for the package with import path The standard packages are given short names like <code>fmt</code> and
<code>x/y</code> is, by convention, kept in the <code>net/http</code> for convenience.
directory <code>$GOROOT/src/pkg/x/y</code>. 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>
<h3>Makefile</h3> <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> <p>
It would be nice to have Go-specific tools that If you don't intend your code to be installed in this way, you should at
inspect the source files to determine what to build and in least use a unique prefix like "<code>widgets/</code>", as in
what order, but for now, Go uses GNU <code>make</code>. "<code>widgets/foo/bar</code>". A good rule is to use a prefix such as your
Thus, the first file to create in a new package directory is company or project name since it is unlikely to be used by another group.
usually the <code>Makefile</code>. </p>
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>:
<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> </p>
<pre> <pre>
include ../../../Make.inc $ export GOPATH=$HOME/gocode
$ mkdir -p $GOPATH/src/widgets/foo
TARG=container/vector $ cat &gt; $GOPATH/src/widgets/foo/foo.go
GOFILES=\ package foo
intvector.go\ const String = "Go rules!"
stringvector.go\ ^D
vector.go\ $ go install widgets/foo
$ ls $GOPATH/pkg/*/example
include ../../../Make.pkg foo.a
</pre> </pre>
<p> <p>(<code>^D</code> means to type Control-D.)</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> <p>
The first and last lines <code>include</code> standard definitions and rules. Type <code>go help gopath</code> on the command line for more information
Packages maintained in the standard Go tree use a relative path (instead of about <code>GOPATH</code>.
<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> </p>
<h3>Go source files</h3> <h3>Go source files</h3>
<p> <p>
The first statement in each of the source files listed in the <code>Makefile</code> The first statement in a Go source file should be <code>package
should be <code>package <i>name</i></code>, where <code><i>name</i></code> <i>name</i></code>, where <code><i>name</i></code> is the package's default
is the package's default name for imports. name for imports.
(All files in a package must use the same <code><i>name</i></code>.) (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 Go's convention is that the package name is the last element of the
import path: the package imported as <code>"crypto/rot13"</code> import path: the package imported as "<code>crypto/rot13</code>"
should be named <code>rot13</code>. should be named <code>rot13</code>.
There is no requirement that package names be unique There is no requirement that package names be unique
across all packages linked into a single binary, across all packages linked into a single binary,
@ -178,63 +147,81 @@ that topic.
</p> </p>
<h2 id="Building_programs">Building programs</h2> <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> <p>
include $(GOROOT)/src/Make.inc 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
TARG=helloworld binary to the <code>GOPATH</code>'s <code>bin</code> subdirectory.
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>
<p> <p>
Running <code>gomake install</code> will build <code>helloworld</code> if Building executable commands is the same as building packages.
necessary and copy it to the <code>$GOBIN</code> directory Use "<code>go install</code>":
(<code>$GOROOT/bin/</code> is the default). </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> </p>
<h2 id="Testing">Testing</h2> <h2 id="Testing">Testing</h2>
<p> <p>
Go has a lightweight test framework known as <code>gotest</code>. 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> 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>. that contains functions named <code>TestXXX</code> with signature
<code>func (t *testing.T)</code>.
The test framework runs each such function; 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. if the function calls a failure function such as <code>t.Error</code> or
The <a href="/cmd/gotest/">gotest command documentation</a> <code>t.Fail</code>, the test is considered to have failed.
and the <a href="/pkg/testing/">testing package documentation</a> give more detail. Run <code>go help test</code> and see the
<a href="/pkg/testing/">testing package documentation</a> for more detail.
</p> </p>
<p> <p>
The <code>*_test.go</code> files should not be listed in the <code>Makefile</code>. To run the test, run "<code>go test</code>":
</p> </p>
<p> <pre>
To run the test, run either <code>make test</code> or <code>gotest</code> $ cat &gt; $GOPATH/src/widgets/foo/foo_test.go
(they are equivalent). package foo
To run only the tests in a single test file, for instance <code>one_test.go</code>,
run <code>gotest one_test.go</code>. import "testing"
</p>
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> <p>
If your change affects performance, add a <code>Benchmark</code> function If your change affects performance, add a <code>Benchmark</code> function
(see the <a href="/cmd/gotest/">gotest command documentation</a>) (run <code>go help testfunc</code>) and run it using <code>go test
and run it using <code>gotest -test.bench=.</code>. -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> </p>
<h2 id="pkg_example">An example package with tests</h2> <h2 id="pkg_example">An example package with tests</h2>
@ -242,7 +229,7 @@ it's time to get it <a href="contribute.html">reviewed and submitted</a>.
<p> <p>
This example package, <code>numbers</code>, consists of the function This example package, <code>numbers</code>, consists of the function
<code>Double</code>, which takes an <code>int</code> and returns that value <code>Double</code>, which takes an <code>int</code> and returns that value
multiplied by 2. It consists of three files. multiplied by 2. It consists of two files.
</p> </p>
<p> <p>
@ -289,38 +276,24 @@ func TestDouble(t *testing.T) {
</pre> </pre>
<p> <p>
Finally, the <code>Makefile</code>: Running <code>go install</code> will build and install the package to
</p> the <code>GOPATH</code>'s <code>pkg</code> directory
(it can then be imported by any other Go program).
<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>
<p> <p>
Running <code>gomake test</code> (or just running the command Running <code>go test</code> will rebuild the package, including the
<code>gotest</code>) will rebuild the package, including the
<code>numbers_test.go</code> file, and then run the <code>TestDouble</code> <code>numbers_test.go</code> file, and then run the <code>TestDouble</code>
function. The output "<code>PASS</code>" indicates that all tests passed function. The output "<code>ok</code>" indicates that all tests passed
successfully. Breaking the implementation by changing the multiplier from 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 <code>2</code> to <code>3</code> will allow you to see how failing tests are
reported. reported.
</p> </p>
<p> <p>
See the <a href="/cmd/gotest/">gotest documentation</a> and the Run <code>go help test</code>, <code>go help testfunc</code>,
<a href="/pkg/testing/">testing package</a> for more detail. and <code>go help testflag</code> and see the
<a href="/pkg/testing/">testing package documentation</a> for more detail.
</p> </p>
<h2 id="arch_os_specific">Architecture- and operating system-specific code</h2> <h2 id="arch_os_specific">Architecture- and operating system-specific code</h2>
@ -335,34 +308,34 @@ different operating systems.</p>
<p>To compile such code, use the <code>$GOOS</code> and <code>$GOARCH</code> <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 <a href="/doc/install.html#environment">environment variables</a> in your
source file names and <code>Makefile</code>.</p> source file names.</p>
<p>For example, this <code>Makefile</code> describes a package that builds on <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 different operating systems by parameterizing the file name with
<code>$GOOS</code>.</p> <code>$GOOS</code>.</p>
<pre> <p>The general code goes in <code>foo.go</code>, while architecture-specific
include $(GOROOT)/src/Make.inc code goes in <code>foo_386.go</code>, <code>foo_amd64.go</code>, and
<code>foo_arm.go</code>.</p>
TARG=mypackage <p>If you follow these conventional parameterizations, tools such as the <a
GOFILES=\ href="/cmd/go/"><code>go</code> tool</a> will work seamlessly with your
my.go\ package:</p>
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> <pre>
my_$(GOOS).go foo_$GOOS.go
my_$(GOARCH).go foo_$GOARCH.go
my_$(GOOS)_$(GOARCH).go foo_$GOOS_$GOARCH.go
</pre> </pre>
<p>The same holds for <code>.s</code> (assembly) files.</p> <p>The same holds for <code>.s</code> (assembly) and <code>.c</code> files.</p>