Commit d9b82baa authored by Andrew Gerrand's avatar Andrew Gerrand

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
parent 014c342b
...@@ -45,120 +45,89 @@ that receives a message summarizing each checkin to the Go repository. ...@@ -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> <p>
It would be nice to have Go-specific tools that For instance, if your source repository is at <code>example.com</code>
inspect the source files to determine what to build and in or <code>code.google.com/p/example</code>, you should begin your package
what order, but for now, Go uses GNU <code>make</code>. paths with that URL, as in "<code>example.com/foo/bar</code>" or
Thus, the first file to create in a new package directory is "<code>code.google.com/p/example/foo/bar</code>".
usually the <code>Makefile</code>. This way the <a href="/cmd/go/"><code>go</code> tool</a> can automatically
The basic form used in the Go source tree check out and build the source code from its import path.
is illustrated by <a href="../src/pkg/container/vector/Makefile"><code>src/pkg/container/vector/Makefile</code></a>:
</p> </p>
<pre>
include ../../../Make.inc
TARG=container/vector
GOFILES=\
intvector.go\
stringvector.go\
vector.go\
include ../../../Make.pkg
</pre>
<p> <p>
Outside the Go source tree (for personal packages), the standard form is 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> </p>
<pre>
include $(GOROOT)/src/Make.inc
TARG=mypackage
GOFILES=\
my1.go\
my2.go\
include $(GOROOT)/src/Make.pkg <h3>The <code>go</code> tool and <code>GOPATH</code></h3>
</pre>
<p> <p>
The first and last lines <code>include</code> standard definitions and rules. The <a href="/cmd/go/"><code>go</code> tool</a> is the standard means of
Packages maintained in the standard Go tree use a relative path (instead of building and installing Go libraries and programs. It is a "zero configuration"
<code>$(GOROOT)/src</code>) so that <code>make</code> will work correctly tool; it determines how to build Go packages from their source code alone.
even if <code>$(GOROOT)</code> contains spaces.
This makes it easy for programmers to try Go.
</p> </p>
<p> <p>
If you have not set <code>$GOROOT</code> in your environment, To use the <code>go</code> tool effectively you must set the
you must run <code>gomake</code> to use this form of makefile. <code>GOPATH</code> variable.
<code>Gomake</code> also takes care to invoke GNU Make <code>GOPATH</code> specifies a list of paths that contain Go source code
even on systems where it is installed as <code>gmake</code> and package binaries. Source code, package objects, and command binaries are
rather than <code>make</code>. located inside the <code>GOPATH</code>s' <code>src</code>, <code>pkg</code>,
and <code>bin</code> subdirectories respectively.
</p> </p>
<p> <p>
<code>TARG</code> is the target install path for the package, You should set <code>GOPATH</code> in your shell profile
the string that clients will use to import it. (<code>$HOME/.bashrc</code>, <code>$HOME/.profile</code>, or equivalent).
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>
<p> <p>
<code>GOFILES</code> is a list of source files to compile to This shell session demonstrates setting <code>GOPATH</code>, creating a trivial
create the package. The trailing <code>\</code> characters <code>widgets/foo</code> package, and building and installing the package.
allow the list to be split onto multiple lines
for easy sorting.
</p> </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> <pre>
cd $GOROOT/src/pkg $ export GOPATH=$HOME/gocode
./deps.bash $ 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> </pre>
<p>
to update the dependency file <code>Make.deps</code>. <p>(<code>^D</code> means to type Control-D.)</p>
(This happens automatically each time you run <code>all.bash</code>
or <code>make.bash</code>.)
</p>
<p> <p>
If you change the imports of an existing package, Type <code>go help gopath</code> on the command line for more information
you do not need to edit <code>$GOROOT/src/pkg/Makefile</code> about <code>GOPATH</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. ...@@ -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 <p>
<code>Make.cmd</code> instead of <code>Make.pkg</code>: 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> <pre>
include $(GOROOT)/src/Make.inc $ cat &gt; $GOPATH/src/widgets/bar/bar.go
package main
TARG=helloworld import (
GOFILES=\ "fmt"
helloworld.go\ "widgets/foo"
)
include $(GOROOT)/src/Make.cmd func main() {
fmt.Println(foo.String)
}
^D
$ go install widgets/bar
$ $GOPATH/bin/bar
Go rules!
</pre> </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>
Running <code>gomake install</code> will build <code>helloworld</code> if Run <code>go help build</code> and <code>go help install</code> for more
necessary and copy it to the <code>$GOBIN</code> directory about building and installing Go binaries.
(<code>$GOROOT/bin/</code> is the default).
</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>.
</p>
<p> import "testing"
If your change affects performance, add a <code>Benchmark</code> function
(see the <a href="/cmd/gotest/">gotest command documentation</a>) func TestString(t *testing.T) {
and run it using <code>gotest -test.bench=.</code>. const expect = "Go rules!"
</p> if String != expect {
t.Errorf("String == %q, want %q", String, expect)
}
}
^D
$ go test widgets/foo
ok widgets/foo
</pre>
<p> <p>
Once your new code is tested and working, If your change affects performance, add a <code>Benchmark</code> function
it's time to get it <a href="contribute.html">reviewed and submitted</a>. (run <code>go help testfunc</code>) and run it using <code>go test
-test.bench=.*</code>.
</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>. ...@@ -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) { ...@@ -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> ...@@ -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
different operating systems by parameterizing the file name with files:</p>
<code>$GOOS</code>.</p>
<pre> <pre>
include $(GOROOT)/src/Make.inc foo.go
foo_386.go
TARG=mypackage foo_amd64.go
GOFILES=\ foo_arm.go
my.go\
my_$(GOOS).go\
include $(GOROOT)/src/Make.pkg
</pre> </pre>
<p>The OS-specific code goes in <code>my_linux.go</code>, describes a package that builds on
<code>my_darwin.go</code>, and so on.</p> 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 <p>If you follow these conventional parameterizations, tools such as the <a
<a href="/cmd/goinstall/">goinstall</a> will work seamlessly with your package: href="/cmd/go/"><code>go</code> tool</a> will work seamlessly with your
</p> 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>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment