diff options
Diffstat (limited to 'doc/code.html')
-rw-r--r-- | doc/code.html | 474 |
1 files changed, 282 insertions, 192 deletions
diff --git a/doc/code.html b/doc/code.html index 82b211870..f64dd6a2a 100644 --- a/doc/code.html +++ b/doc/code.html @@ -6,344 +6,381 @@ <p> 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, +introduces the <a href="/cmd/go/">go tool</a>, the standard way to fetch, build, and install Go packages and commands. </p> <p> -This content is also available as a <a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>. +The <code>go</code> tool requires you to organize your code in a specific +way. Please read this document carefully. +It explains the simplest way to get up and running with your Go installation. +</p> + +<p> +A similar explanation is available as a +<a href="http://www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>. </p> -<h2 id="GOPATH">Code organization</h2> +<h2 id="Organization">Code organization</h2> -<h3><code>GOPATH</code> and workspaces</h3> +<h3 id="Workspaces">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. +The <code>go</code> tool is designed to work with open source code maintained +in public repositories. Although you don't need to publish your code, the model +for how the environment is set up works the same whether you do or not. </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. +Go code must be kept inside a <i>workspace</i>. +A workspace is a directory hierarchy with three directories at its root: </p> +<ul> +<li><code>src</code> contains Go source files organized into packages (one package per directory), +<li><code>pkg</code> contains package objects, and +<li><code>bin</code> contains executable commands. +</ul> + <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: +The <code>go</code> tool builds source packages and installs the resulting +binaries to the <code>pkg</code> and <code>bin</code> directories. </p> -<pre> -GOPATH=/home/user/ext:/home/user/mygo -</pre> - <p> -(On a Windows system use semicolons as the path separator instead of colons.) +The <code>src</code> subdirectory typically contains multiple version control +repositories (such as for Git or Mercurial) that track the development of one +or more source packages. </p> <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: +To give you an idea of how a workspace looks in practice, here's an example: </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> +<pre> +bin/ + streak # command executable + todo # command executable +pkg/ + linux_amd64/ + code.google.com/p/goauth2/ + oauth.a # package object + github.com/nf/todo/ + task.a # package object +src/ + code.google.com/p/goauth2/ + .hg/ # mercurial repository metadata + oauth/ + oauth.go # package source + oauth_test.go # test source + github.com/nf/ + streak/ + .git/ # git repository metadata + oauth.go # command source + streak.go # command source + todo/ + .git/ # git repository metadata + task/ + task.go # package source + todo.go # command source +</pre> <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. +This workspace contains three repositories (<code>goauth2</code>, +<code>streak</code>, and <code>todo</code>) comprising two commands +(<code>streak</code> and <code>todo</code>) and two libraries +(<code>oauth</code> and <code>task</code>). </p> <p> -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—if the package source isn't found there—it searches -for <code>src/widget</code> inside each workspace in order. +Commands and libraries are built from different kinds of source packages. +We will discuss the distinction <a href="#PackageNames">later</a>. </p> + +<h3 id="GOPATH">The <code>GOPATH</code> environment variable</h3> + <p> -Multiple workspaces can offer some flexibility and convenience, but for now -we'll concern ourselves with only a single workspace. +The <code>GOPATH</code> environment variable specifies the location of your +workspace. It is likely the only environment variable you'll need to set +when developing Go code. </p> <p> -Let's work through a simple example. First, create a <code>$HOME/mygo</code> -directory and its <code>src</code> subdirectory: +To get started, create a workspace directory and set <code>GOPATH</code> +accordingly. Your workspace can be located wherever you like, but we'll use +<code>$HOME/go</code> in this document. Note that this must <b>not</b> be the +same path as your Go installation. </p> <pre> -$ mkdir -p $HOME/mygo/src # create a place to put source code +$ <b>mkdir $HOME/go</b> +$ <b>export GOPATH=$HOME/go</b> </pre> <p> -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): +For convenience, add the workspace's <code>bin</code> subdirectory +to your <code>PATH</code>: </p> <pre> -export GOPATH=$HOME/mygo -export PATH=$PATH:$HOME/mygo/bin +$ <b>export PATH=$PATH:$GOPATH/bin</b> </pre> -<h3>Import paths</h3> +<h3 id="PackagePaths">Package paths</h3> <p> -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. +The packages from the standard library are given short paths such as +<code>"fmt"</code> and <code>"net/http"</code>. +For your own packages, you must choose a base path that is unlikely to +collide with future additions to the standard library or other external +libraries. </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> -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. +If you keep your code in a source repository somewhere, then you should use the +root of that source repository as your base path. +For instance, if you have a <a href="https://github.com/">GitHub</a> account at +<code>github.com/user</code>, that should be your base path. </p> <p> -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. +Note that you don't need to publish your code to a remote repository before you +can build it. It's just a good habit to organize your code as if you will +publish it someday. In practice you can choose any arbitrary path name, +as long as it is unique to the standard library and greater Go ecosystem. </p> <p> -We'll use <code>example/</code> as our base import path: +We'll use <code>github.com/user</code> as our base path. Create a directory +inside your workspace in which to keep source code: </p> <pre> -$ mkdir -p $GOPATH/src/example +$ <b>mkdir -p $GOPATH/src/github.com/user</b> </pre> -<h3>Package names</h3> +<h3 id="Command">Your first program</h3> <p> -The first statement in a Go source file should be +To compile and run a simple program, first choose a package path (we'll use +<code>github.com/user/hello</code>) and create a corresponding package directory +inside your workspace: </p> <pre> -package <i>name</i> +$ <b>mkdir $GOPATH/src/github.com/user/hello</b> </pre> <p> -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>.) +Next, create a file named <code>hello.go</code> inside that directory, +containing the following Go 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>" -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> +<pre> +package main -<p> -Create a new package under <code>example</code> called <code>newmath</code>: -</p> +import "fmt" -<pre> -$ cd $GOPATH/src/example -$ mkdir newmath +func main() { + fmt.Printf("Hello, world.\n") +} </pre> <p> -Then create a file named <code>$GOPATH/src/example/newmath/sqrt.go</code> -containing the following Go code: +Now you can build and install that program with the <code>go</code> tool: </p> <pre> -// 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 -} +$ <b>go install github.com/user/hello</b> </pre> <p> -This package is imported by the path name of the directory it's in, starting -after the <code>src</code> component: +Note that you can run this command from anywhere on your system. The +<code>go</code> tool finds the source code by looking for the +<code>github.com/user/hello</code> package inside the workspace specified by +<code>GOPATH</code>. +</p> + +<p> +You can also omit the package path if you run <code>go install</code> from the +package directory: </p> <pre> -import "example/newmath" +$ <b>cd $GOPATH/src/github.com/user/hello</b> +$ <b>go install</b> </pre> <p> -See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about -Go's naming conventions. +This command builds the <code>hello</code> command, producing an executable +binary. It then installs that binary to the workspace's <code>bin</code> +directory as <code>hello</code> (or, under Windows, <code>hello.exe</code>). +In our example, that will be <code>$GOPATH/bin/hello</code>, which is +<code>$HOME/go/bin/hello</code>. </p> - -<h2>Building and installing</h2> +<p> +The <code>go</code> tool will only print output when an error occurs, so if +these commands produce no output they have executed successfully. +</p> <p> -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. +You can now run the program by typing its full path at the command line: </p> +<pre> +$ <b>$GOPATH/bin/hello</b> +Hello, world. +</pre> + <p> -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. +Or, as you have added <code>$GOPATH/bin</code> to your <code>PATH</code>, +just type the binary name: </p> -<h3>Building a package</h3> +<pre> +$ <b>hello</b> +Hello, world. +</pre> <p> -To build and install the <code>newmath</code> package, type +If you're using a source control system, now would be a good time to initialize +a repository, add the files, and commit your first change. Again, this step is +optional: you do not need to use source control to write Go code. </p> <pre> -$ go install example/newmath +$ <b>cd $GOPATH/src/github.com/user/hello</b> +$ <b>git init</b> +Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/ +$ <b>git add hello.go</b> +$ <b>git commit -m "initial commit"</b> +[master (root-commit) 0b4507d] initial commit + 1 file changed, 1 insertion(+) + create mode 100644 hello.go </pre> <p> -This command will produce no output if the package and its dependencies -are built and installed correctly. +Pushing the code to a remote repository is left as an exercise for the reader. +</p> + + +<h3 id="Library">Your first library</h3> + +<p> +Let's write a library and use it from the <code>hello</code> program. </p> <p> -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 effect as the one above: +Again, the first step is to choose a package path (we'll use +<code>github.com/user/newmath</code>) and create the package directory: </p> <pre> -$ cd $GOPATH/src/example/newmath -$ go install +$ <b>mkdir $GOPATH/src/github.com/user/newmath</b> </pre> <p> -The resulting workspace directory tree (assuming we're running Linux on a 64-bit -system) looks like this: +Next, create a file named <code>sqrt.go</code> in that directory with the +following contents. </p> <pre> -pkg/ - linux_amd64/ - example/ - newmath.a # package object -src/ - example/ - newmath/ - sqrt.go # package source -</pre> - +// Package newmath is a trivial example package. +package newmath -<h3>Building a command</h3> +// Sqrt returns an approximation to the square root of x. +func Sqrt(x float64) float64 { + z := 0.0 + for i := 0; i < 1000; i++ { + z -= (z*z - x) / (2 * x) + } + return z +} +</pre> <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. +Now, test that the package compiles with <code>go build</code>: </p> +<pre> +$ <b>go build github.com/user/newmath</b> +</pre> + <p> -Add a command named <code>hello</code> to the source tree. -First create the <code>example/hello</code> directory: +Or, if you are working in the package's source directory, just: </p> <pre> -$ cd $GOPATH/src/example -$ mkdir hello +$ <b>go build</b> </pre> <p> -Then create the file <code>$GOPATH/src/example/hello/hello.go</code> -containing the following Go code. +This won't produce an output file. To do that, you must use <code>go +install</code>, which places the package object inside the <code>pkg</code> +directory of the workspace. +</p> + +<p> +After confirming that the <code>newmath</code> package builds, +modify your original <code>hello.go</code> (which is in +<code>$GOPATH/src/github.com/user/hello</code>) to use it: </p> <pre> -// Hello is a trivial example of a main package. package main import ( - "example/newmath" - "fmt" + "fmt" + + <b>"github.com/user/newmath"</b> ) func main() { - fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2)) + fmt.Printf("Hello, world. <b>Sqrt(2) = %v\n", newmath.Sqrt(2)</b>) } </pre> <p> -Next, run <code>go install</code>, which builds and installs the binary to -<code>$GOPATH/bin</code> (or <code>$GOBIN</code>, if set; to simplify -presentation, this document assumes <code>GOBIN</code> is unset): +Whenever the <code>go</code> tool installs a package or binary, it also +installs whatever dependencies it has. So when you install the <code>hello</code> +program </p> <pre> -$ go install example/hello +$ <b>go install github.com/user/hello</b> </pre> <p> -To run the program, invoke it by name as you would any other command: +the <code>newmath</code> package will be installed as well, automatically. </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: +Running the new version of the program, you should see some numerical output: </p> <pre> -$ hello +$ <b>hello</b> Hello, world. Sqrt(2) = 1.414213562373095 </pre> <p> -The workspace directory tree now looks like this: +After the steps above, your workspace should look like this: </p> <pre> bin/ hello # command executable pkg/ - linux_amd64/ - example/ + linux_amd64/ # this will reflect your OS and architecture + github.com/user/ newmath.a # package object src/ - example/ + github.com/user/ hello/ hello.go # command source newmath/ @@ -351,13 +388,55 @@ src/ </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.) +Note that <code>go install</code> placed the <code>newmath.a</code> object in a +directory inside <code>pkg/linux_amd64</code> that mirrors its source +directory. +This is so that future invocations of the <code>go</code> tool can find the +package object and avoid recompiling the package unnecessarily. +The <code>linux_amd64</code> part is there to aid in cross-compilation, +and will reflect the operating system and architecture of your system. +</p> + +<p> +Go command executables are statically linked; the package objects need not +be present to run Go programs. +</p> + + +<h3 id="PackageNames">Package names</h3> + +<p> +The first statement in a Go source file must be +</p> + +<pre> +package <i>name</i> +</pre> + +<p> +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>" +should be named <code>rot13</code>. +</p> + +<p> +Executable commands must always use <code>package main</code>. +</p> + +<p> +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> +See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about +Go's naming conventions. </p> @@ -379,8 +458,8 @@ if the function calls a failure function such as <code>t.Error</code> or <p> 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. +<code>$GOPATH/src/github.com/user/newmath/sqrt_test.go</code> containing the +following Go code. </p> <pre> @@ -392,17 +471,27 @@ func TestSqrt(t *testing.T) { const in, out = 4, 2 if x := Sqrt(in); x != out { t.Errorf("Sqrt(%v) = %v, want %v", in, x, out) - } + } } </pre> <p> -Now run the test with <code>go test</code>: +Then run the test with <code>go test</code>: +</p> + +<pre> +$ <b>go test github.com/user/newmath</b> +ok github.com/user/newmath 0.165s +</pre> + +<p> +As always, if you are running the <code>go</code> tool from the package +directory, you can omit the package path: </p> <pre> -$ go test example/newmath -ok example/newmath 0.165s +$ <b>go test</b> +ok github.com/user/newmath 0.165s </pre> <p> @@ -415,7 +504,7 @@ Run <code><a href="/cmd/go/#hdr-Test_packages">go help test</a></code> and see t <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 +revision control system such as Git or Mercurial. The <code>go</code> tool 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, @@ -425,8 +514,8 @@ If you include the repository URL in the package's import path, </p> <pre> -$ go get code.google.com/p/go.example/hello -$ $GOPATH/bin/hello +$ <b>go get code.google.com/p/go.example/hello</b> +$ <b>$GOPATH/bin/hello</b> Hello, world. Sqrt(2) = 1.414213562373095 </pre> @@ -439,17 +528,17 @@ fetch and behaves the same as <code>go install</code>.) <p> After issuing the above <code>go get</code> command, the workspace directory -tree should now now look like this: +tree should now look like this: </p> <pre> bin/ hello # command executable pkg/ - linux_amd64/ + linux_amd64/ code.google.com/p/go.example/ newmath.a # package object - example/ + github.com/user/ newmath.a # package object src/ code.google.com/p/go.example/ @@ -458,7 +547,7 @@ src/ newmath/ sqrt.go # package source sqrt_test.go # test source - example/ + github.com/user/ hello/ hello.go # command source newmath/ @@ -480,12 +569,13 @@ import "code.google.com/p/go.example/newmath" <p> This convention is the easiest way to make your Go packages available for others to use. -The <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Community Wiki</a> -has a list of external Go projects including programs and libraries. +The <a href="http://code.google.com/p/go-wiki/wiki/Projects">Go Wiki</a> +and <a href="http://godoc.org/">godoc.org</a> +provide lists of external Go projects. </p> <p> -For more information on using remote repositories with the <code>go</code> command, see +For more information on using remote repositories with the <code>go</code> tool, see <code><a href="/cmd/go/#hdr-Remote_import_path_syntax">go help remote</a></code>. </p> |