From ee923e3f907adbe99352fe27a5a4994f7d9c4917 Mon Sep 17 00:00:00 2001
From: Andrew Gerrand
This document demonstrates the development of a simple Go package and
-introduces the go command, the standard way to fetch,
+introduces the go tool, the standard way to fetch,
build, and install Go packages and commands.
-This content is also available as a screencast.
+The
+A similar explanation is available as a
+screencast.
-One of Go's design goals is to make writing software easier. To that end, the
-
-The one thing you must do is set a
-
-(On a Windows system use semicolons as the path separator instead of colons.)
+The
-Each path in the list (in this case
-Subdirectories of the
-When building a program that imports the package "
-Multiple workspaces can offer some flexibility and convenience, but for now
-we'll concern ourselves with only a single workspace.
+The
-Let's work through a simple example. First, create a
-Next, set it as the
-The standard packages are given short import paths such as
-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
-If you don't intend to install your code in this way, you should at
-least use a unique prefix like "
-We'll use
-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
+
-where
-Go's convention is that the package name is the last element of the
-import path: the package imported as "
-Create a new package under
-Then create a file named
-This package is imported by the path name of the directory it's in, starting
-after the
+You can also omit the package path if you run
-See Effective Go to learn more about
-Go's naming conventions.
+This command builds the
+The
-The
-To "install a package" means to write the package object or executable command
-to the
-To build and install the
-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.
+
+Let's write a library and use it from the
-As a convenience, the
-The resulting workspace directory tree (assuming we're running Linux on a 64-bit
-system) looks like this:
+Next, create a file named
-The
-Add a command named
-Then create the file
+After confirming that the
-Next, run
-To run the program, invoke it by name as you would any other command:
+the
-If you added
-The workspace directory tree now looks like this:
+After the steps above, your workspace should look like this:
-The
+Go command exectuables are statically linked; the package objects need not
+be present to run Go programs.
+
+The first statement in a Go source file must be
+
+where
+Go's convention is that the package name is the last element of the
+import path: the package imported as "
+Executable commands must always use
+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.
+
+See Effective Go to learn more about
+Go's naming conventions.
Add a test to the
-Now run the test with
+As always, if you are running the
@@ -415,7 +504,7 @@ Run
An import path can describe how to obtain the package source code using a
-revision control system such as Git or Mercurial. The go
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.
+Code organization
-
+GOPATH
and workspacesWorkspaces
go
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 go
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.
GOPATH
environment variable.
-GOPATH
tells the go
command (and other related tools)
-where to find and install the Go packages on your system.
+Go code must be kept inside a workspace.
+A workspace is a directory hierarchy with three directories at its root:
+
+
src
contains Go source files organized into packages (one package per directory),
+pkg
contains package objects, and
+bin
contains executable commands.
+GOPATH
is a list of paths. It shares the syntax of your system's
-PATH
environment variable. A typical GOPATH
on
-a Unix system might look like this:
+The go
tool builds source packages and installs the resulting
+binaries to the pkg
and bin
directories.
-GOPATH=/home/user/ext:/home/user/mygo
-
-
src
subdirectory typically contains multiple version control
+repositories (such as for Git or Mercurial) that track the development of one
+or more source packages.
/home/user/ext
or
-/home/user/mygo
) specifies the location of a workspace.
-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:
-
+src
contains Go source files,
-pkg
contains compiled package objects, and
-bin
contains executable commands.
-
+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
+
src
directory hold independent packages, and
-all source files (.go
, .c
, .h
, and
-.s
) in each subdirectory are elements of that subdirectory's
-package.
+This workspace contains three repositories (goauth2
,
+streak
, and todo
) comprising two commands
+(streak
and todo
) and two libraries
+(oauth
and task
).
widget
" the
-go
command looks for src/pkg/widget
inside the Go root,
-and then—if the package source isn't found there—it searches
-for src/widget
inside each workspace in order.
+Commands and libraries are built from different kinds of source packages.
+We will discuss the distinction later.
The
+
GOPATH
environment variableGOPATH
environment variable specifies the location of your
+workspace. It is likely the only environment variable you'll need to set
+when developing Go code.
$HOME/mygo
-directory and its src
subdirectory:
+To get started, create a workspace directory and set GOPATH
+accordingly. Your workspace can be located wherever you like, but we'll use
+$HOME/go
in this document. Note that this must not be the
+same path as your Go installation.
-$ mkdir -p $HOME/mygo/src # create a place to put source code
+$ mkdir $HOME/go
+$ export GOPATH=$HOME/go
GOPATH
. You should also add the
-bin
subdirectory to your PATH
environment variable so
-that you can run the commands therein without specifying their full path.
-To do this, add the following lines to $HOME/.profile
(or
-equivalent):
+For convenience, add the workspace's bin
subdirectory
+to your PATH
:
-export GOPATH=$HOME/mygo
-export PATH=$PATH:$HOME/mygo/bin
+$ export PATH=$PATH:$HOME/go/bin
-Import paths
+Package paths
"fmt"
-and "net/http"
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
+"fmt"
and "net/http"
.
+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.
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
".
-Using this convention, the go
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 GitHub account at
+github.com/user
, that should be your base path.
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.
+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.
example/
as our base import path:
+We'll use github.com/user
as our base path. Create a directory
+inside your workspace in which to keep source code:
-$ mkdir -p $GOPATH/src/example
+$ mkdir -p $GOPATH/src/github.com/user
-Package names
+Your first program
github.com/user/hello
) and create a corresponding package directory
+inside your workspace:
-package name
+$ mkdir $GOPATH/src/github.com/user/hello
name
is the package's default name for imports.
-(All files in a package must use the same name
.)
+Next, create a file named hello.go
inside that directory,
+containing the following Go code.
crypto/rot13
"
-should be named rot13
.
-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.
-
+package main
-
example
called newmath
:
-
-$ cd $GOPATH/src/example
-$ mkdir newmath
+func main() {
+ fmt.Printf("Hello, world.\n")
+}
$GOPATH/src/example/newmath/sqrt.go
-containing the following Go code:
+Now you can build and install that program with the go
tool:
-// 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
-}
+$ go install github.com/user/hello
src
component:
+Note that you can run this command from anywhere on your system. The
+go
tool finds the source code by looking for the
+github.com/user/hello
package inside the workspace specified by
+GOPATH
.
+go install
from the
+package directory:
-import "example/newmath"
+$ cd $GOPATH/src/github.com/user/hello
+$ go install
hello
command, producing an executable
+binary. It then installs that binary to the workspace's bin
+directory as hello
(or, under Windows, hello.exe
).
+In our example, tha will be $GOPATH/bin/hello
, which is
+$HOME/go/bin/hello
.
Building and installing
+go
tool will only print output when an error occurs, so if
+these commands produce no output they have executed successfully.
+go
command comprises several subcommands, the most central being
-install
. Running go install importpath
builds
-and installs a package and its dependencies.
+You can now run the program by typing its full path at the command line:
+$ $GOPATH/bin/hello
+Hello!
+
+
pkg
or bin
subdirectory of the workspace in
-which the source resides.
+Or, as you have added $GOPATH/bin
to your PATH
,
+just type the binary name:
Building a package
+
+$ hello
+Hello!
+
newmath
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.
-$ go install example/newmath
+$ cd $GOPATH/src/github.com/user/hello
+$ git init
+Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/
+$ git add hello.go
+$ git commit -m "initial commit"
+[master (root-commit) 0b4507d] initial commit
+ 1 file changed, 1 insertion(+)
+ create mode 100644 hello.go
Your first library
+
+hello
program.
go
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
+github.com/user/newmath
) and create the package directory:
-$ cd $GOPATH/src/example/newmath
-$ go install
+$ mkdir $GOPATH/src/github.com/user/newmath
sqrt.go
in that directory with the
+following contents.
-pkg/
- linux_amd64/
- example/
- newmath.a # package object
-src/
- example/
- newmath/
- sqrt.go # package source
-
-
+// Package newmath is a trivial example package.
+package newmath
-Building a command
+// 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
+}
+go
command treats code belonging to package main
as
-an executable command and installs the package binary to the
-GOPATH
's bin
subdirectory.
+Now, test that the package compiles with go build
:
+$ go build github.com/user/newmath
+
+
hello
to the source tree.
-First create the example/hello
directory:
+Or, if you are working in the package's source directory, just:
-$ cd $GOPATH/src/example
-$ mkdir hello
+$ go build
$GOPATH/src/example/hello/hello.go
-containing the following Go code.
+This won't produce an output file. To do that, you must use go
+install
, which places the package object inside the pkg
+directory of the workspace.
+newmath
package builds,
+modify your original hello.go
(which is in
+$GOPATH/src/github.com/user/hello
) to use it:
-// Hello is a trivial example of a main package.
package main
import (
- "example/newmath"
- "fmt"
+ "fmt"
+
+ "github.com/user/newmath"
)
func main() {
- fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2))
+ fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2))
}
go install
, which builds and installs the binary to
-$GOPATH/bin
(or $GOBIN
, if set; to simplify
-presentation, this document assumes GOBIN
is unset):
+Whenever the go
tool installs a package or binary, it also
+installs whatever dependencies it has. So when you install the hello
+program
-$ go install example/hello
+$ go install github.com/user/hello
newmath
package will be installed as well, automatically.
-$ $GOPATH/bin/hello
-Hello, world. Sqrt(2) = 1.414213562373095
-
-
$HOME/mygo/bin
to your PATH
, you may omit
-the path to the executable:
+Running the new version of the program, you should see some numerical output:
-$ hello
+$ hello
Hello, world. Sqrt(2) = 1.414213562373095
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/
go
command also provides a build
command, which is
-like install
except it builds all objects in a temporary directory
-and does not install them under pkg
or bin
.
-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,
-go build
serves merely to test that the package and its
-dependencies can be built. (The resulting package object is thrown away.)
+Note that go install
placed the newmath.a
object in a
+directory inside pkg/linux_amd64
that mirrors its source
+directory.
+This is so that future invocations of the go
tool can find the
+package object and avoid recompiling the package unnecessarily.
+The linux_amd64
part is there to aid in cross-compilation,
+and will reflect the operating system and architecture of your system.
+Package names
+
+
+package name
+
+
+name
is the package's default name for imports.
+(All files in a package must use the same name
.)
+crypto/rot13
"
+should be named rot13
.
+package main
.
+t.Error
or
newmath
package by creating the file
-$GOPATH/src/example/newmath/sqrt_test.go
containing the following
-Go code.
+$GOPATH/src/github.com/user/newmath/sqrt_test.go
containing the
+following Go code.
@@ -397,12 +476,22 @@ func TestSqrt(t *testing.T) {
go test
:
+Then run the test with go test
:
+
+$ go test github.com/user/newmath
+ok github.com/user/newmath 0.165s
+
+
+go
tool from the package
+directory, you can omit the package path:
-$ go test example/newmath
-ok example/newmath 0.165s
+$ go test
+ok github.com/user/newmath 0.165s
go help test
and see t
go
command uses
+revision control system such as Git or Mercurial. The go
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,
-$ go get code.google.com/p/go.example/hello
-$ $GOPATH/bin/hello
+$ go get code.google.com/p/go.example/hello
+$ $GOPATH/bin/hello
Hello, world. Sqrt(2) = 1.414213562373095
@@ -449,7 +538,7 @@ pkg/
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/
@@ -485,7 +574,7 @@ has a list of external Go projects including programs and libraries.
-For more information on using remote repositories with the go
command, see
+For more information on using remote repositories with the go
tool, see
go help remote
.