Commit 718de6f4 authored by Andrew Gerrand's avatar Andrew Gerrand

doc: expand code.html to discuss the go tool in more depth

R=golang-dev, balasanjay, r
CC=golang-dev
https://golang.org/cl/5640045
parent c3fbc9a5
...@@ -5,340 +5,499 @@ ...@@ -5,340 +5,499 @@
<h2 id="Introduction">Introduction</h2> <h2 id="Introduction">Introduction</h2>
<p> <p>
This document explains how to write a new package This document demonstrates the development of a simple Go package and
and how to test code. introduces the <a href="/cmd/go/">go command</a>, the standard way to fetch,
It assumes you have installed Go using the build, and install Go packages and commands.
<a href="install.html">installation instructions</a>.
</p> </p>
<h2 id="GOPATH">Code organization</h2>
<h3><code>GOPATH</code> and workspaces</h3>
<p>
One of Go's design goals is to make writing software easier. To that end, the
<code>go</code> command doesn't use Makefiles or other configuration files to
guide program construction. Instead, it uses the source code to find
dependencies and determine build conditions. This means your source code and
build scripts are always in sync; they are one and the same.
</p>
<p>
The one thing you must do is set a <code>GOPATH</code> environment variable.
<code>GOPATH</code> tells the <code>go</code> command (and other related tools)
where to find and install the Go packages on your system.
</p>
<p>
<code>GOPATH</code> is a list of paths. It shares the syntax of your system's
<code>PATH</code> environment variable. A typical <code>GOPATH</code> on
a Unix system might look like this:
</p>
<pre>
GOPATH=/home/user/ext:/home/user/mygo
</pre>
<p> <p>
Before embarking on a change to an existing (On a Windows system use semicolons as the path separator instead of colons.)
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> </p>
<h2 id="Community_resources">Community resources</h2> <p>
Each path in the list (in this case <code>/home/user/ext</code> or
<code>/home/user/mygo</code>) specifies the location of a <i>workspace</i>.
A workspace contains Go source files and their associated package objects, and
command executables. It has a prescribed structure of three subdirectories:
</p>
<ul>
<li><code>src</code> contains Go source files,
<li><code>pkg</code> contains compiled package objects, and
<li><code>bin</code> contains executable commands.</code>
</ul>
<p>
Subdirectories of the <code>src</code> directory hold independent packages, and
all source files (<code>.go</code>, <code>.c</code>, <code>.h</code>, and
<code>.s</code>) in each subdirectory are elements of that subdirectory's
package.
</p>
<p> <p>
For real-time help, there may be users or developers on When building a program that imports the package "<code>widget</code>" the
<code>#go-nuts</code> on the <a href="http://freenode.net/">Freenode</a> IRC server. <code>go</code> command looks for <code>src/pkg/widget</code> inside the Go root,
and then&mdash;if the package source isn't found there&mdash;it searches
for <code>src/widget</code> inside each workspace in order.
</p> </p>
<p> <p>
The official mailing list for discussion of the Go language is Multiple workspaces can offer some flexibility and convenience, but for now
<a href="http://groups.google.com/group/golang-nuts">Go Nuts</a>. we'll concern ourselves with only a single workspace.
</p> </p>
<p> <p>
Bugs can be reported using the <a href="http://code.google.com/p/go/issues/list">Go issue tracker</a>. Let's work through a simple example. First, create a <code>$HOME/mygo</code>
directory and its <code>src</code> subdirectory:
</p> </p>
<pre>
$ mkdir -p $HOME/mygo/src # create a place to put source code
</pre>
<p> <p>
For those who wish to keep up with development, Next, set it as the <code>GOPATH</code>. You should also add the
there is another mailing list, <a href="http://groups.google.com/group/golang-checkins">golang-checkins</a>, <code>bin</code> subdirectory to your <code>PATH</code> environment variable so
that receives a message summarizing each checkin to the Go repository. that you can run the commands therein without specifying their full path.
To do this, add the following lines to <code>$HOME/.profile</code> (or
equivalent):
</p> </p>
<pre>
export GOPATH=$HOME/mygo
export PATH=$PATH:$HOME/mygo/bin
</pre>
<h2 id="New_package">Creating a new package</h2>
<h3>Choosing an import path</h3> <h3>Import paths</h3>
<p> <p>
The standard packages are given short names like <code>fmt</code> and The standard packages are given short import paths such as <code>"fmt"</code>
<code>net/http</code> for convenience. and <code>"net/http"</code> for convenience.
For your own projects, choose a name space that is unlikely For your own projects, it is important to choose a base import path that is
to collide with future additions to the standard library or other unlikely to collide with future additions to the standard library or other
external libraries. external libraries.
</p> </p>
<p> <p>
The best way to choose an import path is to use the location of your version
control repository.
For instance, if your source repository is at <code>example.com</code> 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 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 paths with that URL, as in "<code>example.com/foo/bar</code>" or
"<code>code.google.com/p/example/foo/bar</code>". "<code>code.google.com/p/example/foo/bar</code>".
This way the <a href="/cmd/go/"><code>go</code> tool</a> can automatically Using this convention, the <code>go</code> command can automatically check out and
check out and build the source code from its import path. build the source code by its import path alone.
</p> </p>
<p> <p>
If you don't intend your code to be installed in this way, you should at If you don't intend to install your code in this way, you should at
least use a unique prefix like "<code>widgets/</code>", as in 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 "<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. company or project name, since it is unlikely to be used by another group.
</p> </p>
<p>
We'll use <code>example/</code> as our base import path:
</p>
<pre>
$ mkdir -p $GOPATH/src/example
</pre>
<h3>The <code>go</code> tool and <code>GOPATH</code></h3> <h3>Package names</h3>
<p> <p>
The <a href="/cmd/go/"><code>go</code> tool</a> is the standard means of The first statement in a Go source file should be
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>
<pre>
package <i>name</i>
</pre>
<p> <p>
To use the <code>go</code> tool effectively you must set the where <code><i>name</i></code> is the package's default name for imports.
<code>GOPATH</code> variable. (All files in a package must use the same <code><i>name</i></code>.)
<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>
<p> <p>
You should set <code>GOPATH</code> in your shell profile Go's convention is that the package name is the last element of the
(<code>$HOME/.bashrc</code>, <code>$HOME/.profile</code>, or equivalent). 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>
Create a new package under <code>example</code> called <code>newmath</code>:
</p> </p>
<pre>
$ cd $GOPATH/src/example
$ mkdir newmath
</pre>
<p> <p>
This shell session demonstrates setting <code>GOPATH</code>, creating a trivial Then create a file named <code>$GOPATH/src/example/newmath/sqrt.go</code>
<code>widgets/foo</code> package, and building and installing the package. containing the following Go code:
</p> </p>
<pre> <pre>
$ export GOPATH=$HOME/gocode // Package newmath is a trivial example package.
$ mkdir -p $GOPATH/src/widgets/foo package newmath
$ cat &gt; $GOPATH/src/widgets/foo/foo.go
package foo // Sqrt returns an approximation to the square root of x.
const String = "Go rules!" func Sqrt(x float64) float64 {
^D // This is a terrible implementation.
$ go install widgets/foo // Real code should import "math" and use math.Sqrt.
$ ls $GOPATH/pkg/*/widgets z := 0.0
foo.a for i := 0; i < 1000; i++ {
z -= (z*z - x) / (2 * x)
}
return z
}
</pre> </pre>
<p>(<code>^D</code> means to type Control-D.)</p> <p>
This package is imported by the path name of the directory it's in, starting
after the <code>src</code> component:
</p>
<pre>
import "example/newmath"
</pre>
<p> <p>
Type <code>go help gopath</code> on the command line for more information See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about
about <code>GOPATH</code>. Go's naming conventions.
</p> </p>
<h3>Go source files</h3> <h2>Building and installing</h3>
<p> <p>
The first statement in a Go source file should be <code>package The <code>go</code> command comprises several subcommands, the most central being
<i>name</i></code>, where <code><i>name</i></code> is the package's default <code>install</code>. Running <code>go install <i>importpath</i></code> builds
name for imports. and installs a package and its dependencies.
(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>
<p> <p>
Go compiles all the source files in a package at once, so one file To "install a package" means to write the package object or executable command
can refer to constants, variables, types, and functions in another to the <code>pkg</code> or <code>bin</code> subdirectory of the workspace in
file without special arrangement or declarations. which the source resides.
</p> </p>
<h3>Building a package</h3>
<p> <p>
Writing clean, idiomatic Go code is beyond the scope of this document. To build and install the <code>newmath</code> package, type
<a href="effective_go.html">Effective Go</a> is an introduction to
that topic.
</p> </p>
<h2 id="Building_programs">Building programs</h2> <pre>
$ go install example/newmath
</pre>
<p> <p>
The <a href="/cmd/go/"><code>go</code> tool</a> treats code belonging to This command will produce no output if the package and its dependencies
<code>package main</code> as an executable command, and installs the package are built and installed correctly.
binary to the <code>GOPATH</code>'s <code>bin</code> subdirectory.
</p> </p>
<p> <p>
Building executable commands is the same as building packages. As a convenience, the <code>go</code> command will assume the current directory
Use "<code>go install</code>": if no import path is specified on the command line. This sequence of commands
has the same affect as the one above:
</p> </p>
<pre> <pre>
$ mkdir -p $GOPATH/src/widgets/bar $ cd $GOPATH/src/example/newmath
$ cat &gt; $GOPATH/src/widgets/bar/bar.go $ go install
</pre>
<p>
The resulting workspace directory tree (assuimg we're running Linux on a 64-bit
system) looks like this:
</p>
<pre>
pkg/
linux_amd64/
example/
newmath.a # package object
src/
example/
newmath/
sqrt.go # package source
</pre>
<h3>Building a command</h3>
<p>
The <code>go</code> command 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>
Add a command named <code>hello</code> to the source tree.
First create the <code>example/hello</code> directory:
</p>
<pre>
$ cd $GOPATH/src/example
$ mkdir hello
</pre>
<p>
Then create the file <code>$GOPATH/src/example/hello/hello.go</code>
containing the following Go code.
</p>
<pre>
// Hello is a trivial example of a main package.
package main package main
import ( import (
"example/newmath"
"fmt" "fmt"
"widgets/foo"
) )
func main() { func main() {
fmt.Println(foo.String) fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2))
} }
^D
$ go install widgets/bar
$ $GOPATH/bin/bar
Go rules!
</pre> </pre>
<p> <p>
Run <code>go help build</code> and <code>go help install</code> for more Next, run <code>go install</code>, which builds and installs the binary to
about building and installing Go binaries. <code>$GOPATH/bin</code>:
</p>
<pre>
$ go install example/hello
</pre>
<p>
To run the program, invoke it by name as you would any other command:
</p> </p>
<pre>
$ $GOPATH/bin/hello
Hello, world. Sqrt(2) = 1.414213562373095
</pre>
<p>
If you added <code>$HOME/mygo/bin</code> to your <code>PATH</code>, you may omit
the path to the executable:
</p>
<pre>
$ hello
Hello, world. Sqrt(2) = 1.414213562373095
</pre>
<p>
The workspace directory tree now looks like this:
</p>
<pre>
bin/
hello # command executable
pkg/
linux_amd64/
example/
newmath.a # package object
src/
example/
hello/
hello.go # command source
newmath/
sqrt.go # package source
</pre>
<p>
The <code>go</code> command also provides a <code>build</code> command, which is
like <code>install</code> except it builds all objects in a temporary directory
and does not install them under <code>pkg</code> or <code>bin</code>.
When building a command an executable named after the last element of the
import path is written to the current directory. When building a package,
<code>go build</code> serves merely to test that the package and its
dependencies can be built. (The resulting package object is thrown away.)
</p>
<h2 id="Testing">Testing</h2> <h2 id="Testing">Testing</h2>
<p> <p>
Go has a lightweight test framework composed of the <code>go</code> tool and Go has a lightweight test framework composed of the <code>go test</code>
the <code>testing</code> package. command and the <code>testing</code> package.
</p>
<p>
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 that contains functions named <code>TestXXX</code> with signature
<code>func (t *testing.T)</code>. <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 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. <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>
<p> <p>
To run the test, run "<code>go test</code>": Add a test to the <code>newmath</code> package by creating the file
<code>$GOPATH/src/example/newmath/sqrt_test.go</code> containing the following
Go code.
</p> </p>
<pre> <pre>
$ cat &gt; $GOPATH/src/widgets/foo/foo_test.go package newmath
package foo
import "testing" import "testing"
func TestString(t *testing.T) { func TestSqrt(t *testing.T) {
const expect = "Go rules!" const in, out = 9, 3
if String != expect { if x := Sqrt(in); x != out {
t.Errorf("String == %q, want %q", String, expect) t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
} }
} }
^D
$ go test widgets/foo
ok widgets/foo 0.018s
</pre> </pre>
<p> <p>
If your change affects performance, add a <code>Benchmark</code> function Now run the test with <code>go test</code>:
(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> <pre>
$ go test example/newmath
ok example/newmath
</pre>
<p> <p>
This example package, <code>numbers</code>, consists of the function Run <code><a href="/cmd/go/#Test_packages">go help test</a></code> and see the
<code>Double</code>, which takes an <code>int</code> and returns that value <a href="/pkg/testing/">testing package documentation</a> for more detail.
multiplied by 2. It consists of two files.
</p> </p>
<h2 id="remote">Remote packages</h3>
<p> <p>
First, the package implementation, <code>numbers.go</code>: An import path can describe how to obtain the package source code using a
revision control system such as Git or Mercurial. The <code>go</code> command uses
this property to automatically fetch packages from remote repositories.
For instance, the examples described in this document are also kept in a
Mercurial repository hosted at Google Code,
<code><a href="http://code.google.com/p/go.example">code.google.com/p/go.example</a></code>.
If you include the repository URL in the package's import path,
<code>go get</code> will fetch, build, and install it automatically:
</p> </p>
<pre> <pre>
package numbers $ go get code.google.com/p/go.example/hello
$ $GOPATH/bin/hello
func Double(i int) int { Hello, world. Sqrt(2) = 1.414213562373095
return i * 2
}
</pre> </pre>
<p> <p>
Next, the tests, <code>numbers_test.go</code>: If the specified package is not present in a workspace, <code>go get</code>
will place it inside the first workspace specified by <code>GOPATH</code>.
(If the package does already exist, <code>go get</code> skips the remote
fetch and behaves the same as <code>go install</code>.)
</p> </p>
<pre> <p>
package numbers After issuing the above <code>go get</code> command, the workspace directory
tree should now now look like this:
import ( </p>
"testing"
)
type doubleTest struct {
in, out int
}
var doubleTests = []doubleTest{
doubleTest{1, 2},
doubleTest{2, 4},
doubleTest{-5, -10},
}
func TestDouble(t *testing.T) { <pre>
for _, dt := range doubleTests { bin/
v := Double(dt.in) hello # command executable
if v != dt.out { pkg/
t.Errorf("Double(%d) = %d, want %d.", dt.in, v, dt.out) linux_amd64/
} code.google.com/p/go.example/
} newmath.a # package object
} example/
newmath.a # package object
src/
code.google.com/p/go.example/
hello/
hello.go # command source
newmath/
sqrt.go # package source
sqrt_test.go # test source
example/
hello/
hello.go # command source
newmath/
sqrt.go # package source
sqrt_test.go # test source
</pre> </pre>
<p> <p>
Running <code>go install</code> will build and install the package to The <code>hello</code> command hosted at Google Code depends on the
the <code>GOPATH</code>'s <code>pkg</code> directory <code>newmath</code> package within the same repository. The imports in
(it can then be imported by any other Go program). <code>hello.go</code> file use the same import path convention, so the <code>go
get</code> command is able to locate and install the dependent package, too.
</p> </p>
<pre>
import "code.google.com/p/go.example/newmath"
</pre>
<p> <p>
Running <code>go test</code> will rebuild the package, including the This convention is the easiest way to make your Go packages available for
<code>numbers_test.go</code> file, and then run the <code>TestDouble</code> others to use.
function. The output "<code>ok</code>" indicates that all tests passed The <a href="http://godashboard.appspot.com/package">Go Package Dashboard</a>
successfully. Breaking the implementation by changing the multiplier from displays a list of packages recently installed with the <code>go</code> command.
<code>2</code> to <code>3</code> will allow you to see how failing tests are
reported.
</p> </p>
<p> <p>
Run <code>go help test</code>, <code>go help testfunc</code>, For more information on using remote repositories with the <code>go</code> command, see
and <code>go help testflag</code> and see the <code><a href="/cmd/go/#Remote_import_path_syntax">go help remote</a></code>.
<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>
<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>
<p>describes a package that builds on <h2 id="more">Further reading</h2>
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 <p>
code goes in <code>foo_386.go</code>, <code>foo_amd64.go</code>, and See <a href="/doc/effective_go.html">Effective Go</a> for tips on writing
<code>foo_arm.go</code>.</p> clear, idiomatic 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> <p>
foo_$GOOS.go Take <a href="http://tour.golang.org/">A Tour of Go</a> to learn the language
foo_$GOARCH.go proper.
foo_$GOOS_$GOARCH.go </p>
</pre>
<p>The same holds for <code>.s</code> (assembly) and <code>.c</code> files.</p> <p>
Visit the <a href="/doc/#articles">documentation page</a> for a set of in-depth
articles about the Go language and its libraries and tools.
</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