From d9b82baac1f25fce52d1a392fb39711fa9462f40 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Thu, 12 Jan 2012 08:25:49 +1100 Subject: [PATCH] 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 --- doc/code.html | 327 +++++++++++++++++++++++--------------------------- 1 file changed, 150 insertions(+), 177 deletions(-) diff --git a/doc/code.html b/doc/code.html index cdc60b0710..4737a38fd8 100644 --- a/doc/code.html +++ b/doc/code.html @@ -45,120 +45,89 @@ that receives a message summarizing each checkin to the Go repository.

Creating a new package

+

Choosing an import path

+

-The source code for the package with import path -x/y is, by convention, kept in the -directory $GOROOT/src/pkg/x/y. +The standard packages are given short names like fmt and +net/http for convenience. +For your own projects, choose a name space that is unlikely +to collide with future additions to the standard library or other +external libraries.

-

Makefile

+

+For instance, if your source repository is at example.com +or code.google.com/p/example, you should begin your package +paths with that URL, as in "example.com/foo/bar" or +"code.google.com/p/example/foo/bar". +This way the go tool can automatically +check out and build the source code from its import path. +

-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 make. -Thus, the first file to create in a new package directory is -usually the Makefile. -The basic form used in the Go source tree -is illustrated by src/pkg/container/vector/Makefile: +If you don't intend your code to be installed in this way, you should at +least use a unique prefix like "widgets/", as in +"widgets/foo/bar". 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. +

+ + +

The go tool and GOPATH

+ +

+The go tool 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. +

+ +

+To use the go tool effectively you must set the +GOPATH variable. +GOPATH specifies a list of paths that contain Go source code +and package binaries. Source code, package objects, and command binaries are +located inside the GOPATHs' src, pkg, +and bin subdirectories respectively. +

+ +

+You should set GOPATH in your shell profile +($HOME/.bashrc, $HOME/.profile, or equivalent). +

+ +

+This shell session demonstrates setting GOPATH, creating a trivial +widgets/foo package, and building and installing the package.

-include ../../../Make.inc
-
-TARG=container/vector
-GOFILES=\
-	intvector.go\
-	stringvector.go\
-	vector.go\
-
-include ../../../Make.pkg
+$ export GOPATH=$HOME/gocode
+$ mkdir -p $GOPATH/src/widgets/foo
+$ cat > $GOPATH/src/widgets/foo/foo.go
+package foo
+const String = "Go rules!"
+^D
+$ go install widgets/foo
+$ ls $GOPATH/pkg/*/example
+foo.a
 
-

-Outside the Go source tree (for personal packages), the standard form is -

- -
-include $(GOROOT)/src/Make.inc
-
-TARG=mypackage
-GOFILES=\
-	my1.go\
-	my2.go\
-
-include $(GOROOT)/src/Make.pkg
-
+

(^D means to type Control-D.)

-The first and last lines include standard definitions and rules. -Packages maintained in the standard Go tree use a relative path (instead of -$(GOROOT)/src) so that make will work correctly -even if $(GOROOT) contains spaces. -This makes it easy for programmers to try Go. -

- -

-If you have not set $GOROOT in your environment, -you must run gomake to use this form of makefile. -Gomake also takes care to invoke GNU Make -even on systems where it is installed as gmake -rather than make. -

- -

-TARG 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 Makefile appears, with the -$GOROOT/src/pkg/ prefix removed. -Outside the Go tree, you can use any TARG 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: myname/tree, myname/filter, etc. -Note that even if you keep your package source outside the -Go tree, running make install installs your -package binaries in the standard location—$GOROOT/pkg—to -make it easy to find them. -

- -

-GOFILES is a list of source files to compile to -create the package. The trailing \ characters -allow the list to be split onto multiple lines -for easy sorting. -

- -

-If you create a new package directory in the Go tree, add it to the list in -$GOROOT/src/pkg/Makefile so that it -is included in the standard build. Then run: -

-cd $GOROOT/src/pkg
-./deps.bash
-
-

-to update the dependency file Make.deps. -(This happens automatically each time you run all.bash -or make.bash.) -

- -

-If you change the imports of an existing package, -you do not need to edit $GOROOT/src/pkg/Makefile -but you will still need to run deps.bash as above. +Type go help gopath on the command line for more information +about GOPATH.

Go source files

-The first statement in each of the source files listed in the Makefile -should be package name, where name -is the package's default name for imports. +The first statement in a Go source file should be package +name, where name is the package's default +name for imports. (All files in a package must use the same name.) Go's convention is that the package name is the last element of the -import path: the package imported as "crypto/rot13" +import path: the package imported as "crypto/rot13" should be named rot13. There is no requirement that package names be unique across all packages linked into a single binary, @@ -178,63 +147,81 @@ that topic.

Building programs

-

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 -Make.cmd instead of Make.pkg: -

-include $(GOROOT)/src/Make.inc
-
-TARG=helloworld
-GOFILES=\
-	helloworld.go\
-
-include $(GOROOT)/src/Make.cmd
-
- -

Running gomake will compile helloworld.go -and produce an executable named helloworld in the current -directory. +

+The go tool treats code belonging to +package main as an executable command, and installs the package +binary to the GOPATH's bin subdirectory.

-Running gomake install will build helloworld if -necessary and copy it to the $GOBIN directory -($GOROOT/bin/ is the default). +Building executable commands is the same as building packages. +Use "go install": +

+ +
+$ cat > $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!
+
+ +

+Run go help build and go help install for more +about building and installing Go binaries.

Testing

-Go has a lightweight test framework known as gotest. +Go has a lightweight test framework composed of the go tool and +the testing package. You write a test by creating a file with a name ending in _test.go -that contains functions named TestXXX with signature func (t *testing.T). +that contains functions named TestXXX with signature +func (t *testing.T). The test framework runs each such function; -if the function calls a failure function such as t.Error or t.Fail, the test is considered to have failed. -The gotest command documentation -and the testing package documentation give more detail. +if the function calls a failure function such as t.Error or +t.Fail, the test is considered to have failed. +Run go help test and see the +testing package documentation for more detail.

-The *_test.go files should not be listed in the Makefile. +To run the test, run "go test":

-

-To run the test, run either make test or gotest -(they are equivalent). -To run only the tests in a single test file, for instance one_test.go, -run gotest one_test.go. -

+
+$ cat > $GOPATH/src/widgets/foo/foo_test.go
+package foo
+
+import "testing"
+
+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
+

If your change affects performance, add a Benchmark function -(see the gotest command documentation) -and run it using gotest -test.bench=.. -

- -

-Once your new code is tested and working, -it's time to get it reviewed and submitted. +(run go help testfunc) and run it using go test +-test.bench=.*.

An example package with tests

@@ -242,7 +229,7 @@ it's time to get it reviewed and submitted.

This example package, numbers, consists of the function Double, which takes an int and returns that value -multiplied by 2. It consists of three files. +multiplied by 2. It consists of two files.

@@ -289,38 +276,24 @@ func TestDouble(t *testing.T) {

-Finally, the Makefile: -

- -
-include $(GOROOT)/src/Make.inc
-
-TARG=numbers
-GOFILES=\
-	numbers.go\
-
-include $(GOROOT)/src/Make.pkg
-
- -

-Running gomake install will build and install the package to -the $GOROOT/pkg/ directory (it can then be used by any -program on the system). +Running go install will build and install the package to +the GOPATH's pkg directory +(it can then be imported by any other Go program).

-Running gomake test (or just running the command -gotest) will rebuild the package, including the +Running go test will rebuild the package, including the numbers_test.go file, and then run the TestDouble -function. The output "PASS" indicates that all tests passed +function. The output "ok" indicates that all tests passed successfully. Breaking the implementation by changing the multiplier from 2 to 3 will allow you to see how failing tests are reported.

-See the gotest documentation and the -testing package for more detail. +Run go help test, go help testfunc, +and go help testflag and see the +testing package documentation for more detail.

Architecture- and operating system-specific code

@@ -335,34 +308,34 @@ different operating systems.

To compile such code, use the $GOOS and $GOARCH environment variables in your -source file names and Makefile.

+source file names.

-

For example, this Makefile describes a package that builds on +

For example, consider the package foo that consists of four +files:

+ +
+foo.go
+foo_386.go
+foo_amd64.go
+foo_arm.go
+
+ +describes a package that builds on different operating systems by parameterizing the file name with $GOOS.

-
-include $(GOROOT)/src/Make.inc
+

The general code goes in foo.go, while architecture-specific +code goes in foo_386.go, foo_amd64.go, and +foo_arm.go.

-TARG=mypackage -GOFILES=\ - my.go\ - my_$(GOOS).go\ - -include $(GOROOT)/src/Make.pkg -
- -

The OS-specific code goes in my_linux.go, -my_darwin.go, and so on.

- -

If you follow these conventional parameterizations, tools such as -goinstall will work seamlessly with your package: -

+

If you follow these conventional parameterizations, tools such as the go tool will work seamlessly with your +package:

-my_$(GOOS).go
-my_$(GOARCH).go
-my_$(GOOS)_$(GOARCH).go
+foo_$GOOS.go
+foo_$GOARCH.go
+foo_$GOOS_$GOARCH.go
 
-

The same holds for .s (assembly) files.

+

The same holds for .s (assembly) and .c files.