summaryrefslogtreecommitdiff
path: root/doc/code.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/code.html')
-rw-r--r--doc/code.html563
1 files changed, 349 insertions, 214 deletions
diff --git a/doc/code.html b/doc/code.html
index cdc60b071..238cb0643 100644
--- a/doc/code.html
+++ b/doc/code.html
@@ -1,164 +1,158 @@
-<!-- How to Write Go Code -->
+<!--{
+ "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>.
+This document demonstrates the development of a simple Go package and
+introduces the <a href="/cmd/go/">go command</a>, the standard way to fetch,
+build, and install Go packages and commands.
</p>
+
+<h2 id="GOPATH">Code organization</h2>
+
+<h3><code>GOPATH</code> and workspaces</h3>
+
<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.
+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>
-<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.
+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>
-The official mailing list for discussion of the Go language is
-<a href="http://groups.google.com/group/golang-nuts">Go Nuts</a>.
+<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>
-Bugs can be reported using the <a href="http://code.google.com/p/go/issues/list">Go issue tracker</a>.
+(On a Windows system use semicolons as the path separator instead of colons.)
</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.
+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.
+</ul>
-<h2 id="New_package">Creating a new package</h2>
+<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>
-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>.
+When building a program that imports the package "<code>widget</code>" the
+<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>
-<h3>Makefile</h3>
+<p>
+Multiple workspaces can offer some flexibility and convenience, but for now
+we'll concern ourselves with only a single workspace.
+</p>
<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>:
+Let's work through a simple example. First, create a <code>$HOME/mygo</code>
+directory and its <code>src</code> subdirectory:
</p>
<pre>
-include ../../../Make.inc
-
-TARG=container/vector
-GOFILES=\
- intvector.go\
- stringvector.go\
- vector.go\
-
-include ../../../Make.pkg
+$ mkdir -p $HOME/mygo/src # create a place to put source code
</pre>
<p>
-Outside the Go source tree (for personal packages), the standard form is
+Next, set it as the <code>GOPATH</code>. You should also add the
+<code>bin</code> subdirectory to your <code>PATH</code> environment variable so
+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>
<pre>
-include $(GOROOT)/src/Make.inc
+export GOPATH=$HOME/mygo
+export PATH=$PATH:$HOME/mygo/bin
+</pre>
-TARG=mypackage
-GOFILES=\
- my1.go\
- my2.go\
-include $(GOROOT)/src/Make.pkg
-</pre>
+<h3>Import paths</h3>
<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.
+The standard packages are given short import paths such as <code>"fmt"</code>
+and <code>"net/http"</code> for convenience.
+For your own projects, it is important to choose a base import path that is
+unlikely to collide with future additions to the standard library or other
+external libraries.
</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>.
+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>
+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>".
+Using this convention, the <code>go</code> command can automatically check out and
+build the source code by its import path alone.
</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.
+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
+"<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>
-<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.
+We'll use <code>example/</code> as our base import path:
</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
+$ mkdir -p $GOPATH/src/example
</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>
+
+
+<h3>Package names</h3>
<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.
+The first statement in a Go source file should be
</p>
-
-<h3>Go source files</h3>
+<pre>
+package <i>name</i>
+</pre>
<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.
+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>.)
+</p>
+
+<p>
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>.
There is no requirement that package names be unique
across all packages linked into a single binary,
@@ -166,203 +160,344 @@ 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.
+Create a new package under <code>example</code> called <code>newmath</code>:
</p>
+<pre>
+$ cd $GOPATH/src/example
+$ mkdir newmath
+</pre>
+
<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.
+Then create a file named <code>$GOPATH/src/example/newmath/sqrt.go</code>
+containing the following Go code:
</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
+// Package newmath is a trivial example package.
+package newmath
+
+// Sqrt returns an approximation to the square root of x.
+func Sqrt(x float64) float64 {
+ // This is a terrible implementation.
+ // Real code should import "math" and use math.Sqrt.
+ z := 0.0
+ for i := 0; i < 1000; i++ {
+ z -= (z*z - x) / (2 * x)
+ }
+ return z
+}
+</pre>
-TARG=helloworld
-GOFILES=\
- helloworld.go\
+<p>
+This package is imported by the path name of the directory it's in, starting
+after the <code>src</code> component:
+</p>
-include $(GOROOT)/src/Make.cmd
+<pre>
+import "example/newmath"
</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>
+See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about
+Go's naming conventions.
</p>
+
+<h2>Building and installing</h2>
+
<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).
+The <code>go</code> command comprises several subcommands, the most central being
+<code>install</code>. Running <code>go install <i>importpath</i></code> builds
+and installs a package and its dependencies.
</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.
+To "install a package" means to write the package object or executable command
+to the <code>pkg</code> or <code>bin</code> subdirectory of the workspace in
+which the source resides.
</p>
+<h3>Building a package</h3>
+
<p>
-The <code>*_test.go</code> files should not be listed in the <code>Makefile</code>.
+To build and install the <code>newmath</code> package, type
</p>
+<pre>
+$ go install example/newmath
+</pre>
+
<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>.
+This command will produce no output if the package and its dependencies
+are built and installed correctly.
</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>.
+As a convenience, the <code>go</code> command will assume the current directory
+if no import path is specified on the command line. This sequence of commands
+has the same affect as the one above:
</p>
+<pre>
+$ cd $GOPATH/src/example/newmath
+$ go install
+</pre>
+
<p>
-Once your new code is tested and working,
-it's time to get it <a href="contribute.html">reviewed and submitted</a>.
+The resulting workspace directory tree (assuming we're running Linux on a 64-bit
+system) looks like this:
</p>
-<h2 id="pkg_example">An example package with tests</h2>
+<pre>
+pkg/
+ linux_amd64/
+ example/
+ newmath.a # package object
+src/
+ example/
+ newmath/
+ sqrt.go # package source
+</pre>
+
+
+<h3>Building a command</h3>
<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.
+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>
-First, the package implementation, <code>numbers.go</code>:
+Add a command named <code>hello</code> to the source tree.
+First create the <code>example/hello</code> directory:
</p>
<pre>
-package numbers
-
-func Double(i int) int {
- return i * 2
-}
+$ cd $GOPATH/src/example
+$ mkdir hello
</pre>
<p>
-Next, the tests, <code>numbers_test.go</code>:
+Then create the file <code>$GOPATH/src/example/hello/hello.go</code>
+containing the following Go code.
</p>
<pre>
-package numbers
+// Hello is a trivial example of a main package.
+package main
import (
- "testing"
+ "example/newmath"
+ "fmt"
)
-type doubleTest struct {
- in, out int
+func main() {
+ fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2))
}
+</pre>
-var doubleTests = []doubleTest{
- doubleTest{1, 2},
- doubleTest{2, 4},
- doubleTest{-5, -10},
-}
+<p>
+Next, run <code>go install</code>, which builds and installs the binary to
+<code>$GOPATH/bin</code>:
+</p>
-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>
+$ go install example/hello
</pre>
<p>
-Finally, the <code>Makefile</code>:
+To run the program, invoke it by name as you would any other command:
</p>
<pre>
-include $(GOROOT)/src/Make.inc
+$ $GOPATH/bin/hello
+Hello, world. Sqrt(2) = 1.414213562373095
+</pre>
-TARG=numbers
-GOFILES=\
- numbers.go\
+<p>
+If you added <code>$HOME/mygo/bin</code> to your <code>PATH</code>, you may omit
+the path to the executable:
+</p>
-include $(GOROOT)/src/Make.pkg
+<pre>
+$ hello
+Hello, world. Sqrt(2) = 1.414213562373095
</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).
+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>
+
+<p>
+Go has a lightweight test framework composed of the <code>go test</code>
+command and the <code>testing</code> package.
</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.
+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.
</p>
<p>
-See the <a href="/cmd/gotest/">gotest documentation</a> and the
-<a href="/pkg/testing/">testing package</a> for more detail.
+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>
-<h2 id="arch_os_specific">Architecture- and operating system-specific code</h2>
+<pre>
+package newmath
-<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>
+import "testing"
-<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>
+func TestSqrt(t *testing.T) {
+ const in, out = 9, 3
+ if x := Sqrt(in); x != out {
+ t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
+ }
+}
+</pre>
-<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>
+<p>
+Now run the test with <code>go test</code>:
+</p>
<pre>
-include $(GOROOT)/src/Make.inc
+$ go test example/newmath
+ok example/newmath
+</pre>
+
+<p>
+Run <code><a href="/cmd/go/#Test_packages">go help test</a></code> and see the
+<a href="/pkg/testing/">testing package documentation</a> for more detail.
+</p>
+
-TARG=mypackage
-GOFILES=\
- my.go\
- my_$(GOOS).go\
+<h2 id="remote">Remote packages</h2>
-include $(GOROOT)/src/Make.pkg
+<p>
+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>
+
+<pre>
+$ go get code.google.com/p/go.example/hello
+$ $GOPATH/bin/hello
+Hello, world. Sqrt(2) = 1.414213562373095
</pre>
-<p>The OS-specific code goes in <code>my_linux.go</code>,
-<code>my_darwin.go</code>, and so on.</p>
+<p>
+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>If you follow these conventional parameterizations, tools such as
-<a href="/cmd/goinstall/">goinstall</a> will work seamlessly with your package:
+<p>
+After issuing the above <code>go get</code> command, the workspace directory
+tree should now now look like this:
</p>
<pre>
-my_$(GOOS).go
-my_$(GOARCH).go
-my_$(GOOS)_$(GOARCH).go
+bin/
+ hello # command executable
+pkg/
+ 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>
-<p>The same holds for <code>.s</code> (assembly) files.</p>
+<p>
+The <code>hello</code> command hosted at Google Code depends on the
+<code>newmath</code> package within the same repository. The imports in
+<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>
+
+<pre>
+import "code.google.com/p/go.example/newmath"
+</pre>
+
+<p>
+This convention is the easiest way to make your Go packages available for
+others to use.
+The <a href="http://godashboard.appspot.com/package">Go Package Dashboard</a>
+displays a list of packages recently installed with the <code>go</code> command.
+</p>
+
+<p>
+For more information on using remote repositories with the <code>go</code> command, see
+<code><a href="/cmd/go/#Remote_import_path_syntax">go help remote</a></code>.
+</p>
+
+
+<h2 id="more">Further reading</h2>
+
+<p>
+See <a href="/doc/effective_go.html">Effective Go</a> for tips on writing
+clear, idiomatic Go code.
+</p>
+
+<p>
+Take <a href="http://tour.golang.org/">A Tour of Go</a> to learn the language
+proper.
+</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>