123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- <!--{
- "Title": "How to Write Go Code"
- }-->
- <h2 id="Introduction">Introduction</h2>
- <p>
- This document demonstrates the development of a simple Go package and
- introduces the <a href="/cmd/go/">go tool</a>, the standard way to fetch,
- build, and install Go packages and commands.
- </p>
- <p>
- 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="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>.
- </p>
- <h2 id="Organization">Code organization</h2>
- <h3 id="Overview">Overview</h3>
- <ul>
- <li>Go programmers typically keep all their Go code in a single <i>workspace</i>.</li>
- <li>A workspace contains many version control <i>repositories</i>
- (managed by Git, for example).</li>
- <li>Each repository contains one or more <i>packages</i>.</li>
- <li>Each package consists of one or more Go source files in a single directory.</li>
- <li>The path to a package's directory determines its <i>import path</i>.</li>
- </ul>
- <p>
- Note that this differs from other programming environments in which every
- project has a separate workspace and workspaces are closely tied to version
- control repositories.
- </p>
- <h3 id="Workspaces">Workspaces</h3>
- <p>
- A workspace is a directory hierarchy with three directories at its root:
- </p>
- <ul>
- <li><code>src</code> contains Go source files,
- <li><code>pkg</code> contains package objects, and
- <li><code>bin</code> contains executable commands.
- </ul>
- <p>
- The <code>go</code> tool builds source packages and installs the resulting
- binaries to the <code>pkg</code> and <code>bin</code> directories.
- </p>
- <p>
- 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>
- To give you an idea of how a workspace looks in practice, here's an example:
- </p>
- <pre>
- bin/
- hello # command executable
- outyet # command executable
- pkg/
- linux_amd64/
- github.com/golang/example/
- stringutil.a # package object
- src/
- <a href="https://github.com/golang/example/">github.com/golang/example/</a>
- .git/ # Git repository metadata
- hello/
- hello.go # command source
- outyet/
- main.go # command source
- main_test.go # test source
- stringutil/
- reverse.go # package source
- reverse_test.go # test source
- <a href="https://golang.org/x/image/">golang.org/x/image/</a>
- .git/ # Git repository metadata
- bmp/
- reader.go # package source
- writer.go # package source
- ... (many more repositories and packages omitted) ...
- </pre>
- <p>
- The tree above shows a workspace containing two repositories
- (<code>example</code> and <code>image</code>).
- The <code>example</code> repository contains two commands (<code>hello</code>
- and <code>outyet</code>) and one library (<code>stringutil</code>).
- The <code>image</code> repository contains the <code>bmp</code> package
- and <a href="https://godoc.org/golang.org/x/image">several others</a>.
- </p>
- <p>
- A typical workspace contains many source repositories containing many
- packages and commands. Most Go programmers keep <i>all</i> their Go source code
- and dependencies in a single workspace.
- </p>
- <p>
- 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>
- The <code>GOPATH</code> environment variable specifies the location of your
- workspace. It defaults to a directory named <code>go</code> inside your home directory,
- so <code>$HOME/go</code> on Unix,
- <code>$home/go</code> on Plan 9,
- and <code>%USERPROFILE%\go</code> (usually <code>C:\Users\YourName\go</code>) on Windows.
- </p>
- <p>
- If you would like to work in a different location, you will need to
- <a href="https://golang.org/wiki/SettingGOPATH">set <code>GOPATH</code></a>
- to the path to that directory.
- (Another common setup is to set <code>GOPATH=$HOME</code>.)
- Note that <code>GOPATH</code> must <b>not</b> be the
- same path as your Go installation.
- </p>
- <p>
- The command <code>go</code> <code>env</code> <code>GOPATH</code>
- prints the effective current <code>GOPATH</code>;
- it prints the default location if the environment variable is unset.
- </p>
- <p>
- For convenience, add the workspace's <code>bin</code> subdirectory
- to your <code>PATH</code>:
- </p>
- <pre>
- $ <b>export PATH=$PATH:$(go env GOPATH)/bin</b>
- </pre>
- <p>
- The scripts in the rest of this document use <code>$GOPATH</code>
- instead of <code>$(go env GOPATH)</code> for brevity.
- To make the scripts run as written
- if you have not set GOPATH,
- you can substitute $HOME/go in those commands
- or else run:
- </p>
- <pre>
- $ <b>export GOPATH=$(go env GOPATH)</b>
- </pre>
- <p>
- To learn more about the <code>GOPATH</code> environment variable, see
- <a href="/cmd/go/#hdr-GOPATH_environment_variable"><code>'go help gopath'</code></a>.
- </p>
- <p>
- To use a custom workspace location,
- <a href="https://golang.org/wiki/SettingGOPATH">set the <code>GOPATH</code> environment variable</a>.
- </p>
- <h3 id="ImportPaths">Import paths</h3>
- <p>
- An <i>import path</i> is a string that uniquely identifies a package.
- A package's import path corresponds to its location inside a workspace
- or in a remote repository (explained below).
- </p>
- <p>
- The packages from the standard library are given short import 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>
- 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>
- 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>github.com/user</code> as our base path. Create a directory
- inside your workspace in which to keep source code:
- </p>
- <pre>
- $ <b>mkdir -p $GOPATH/src/github.com/user</b>
- </pre>
- <h3 id="Command">Your first program</h3>
- <p>
- 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>
- $ <b>mkdir $GOPATH/src/github.com/user/hello</b>
- </pre>
- <p>
- Next, create a file named <code>hello.go</code> inside that directory,
- containing the following Go code.
- </p>
- <pre>
- package main
- import "fmt"
- func main() {
- fmt.Printf("Hello, world.\n")
- }
- </pre>
- <p>
- Now you can build and install that program with the <code>go</code> tool:
- </p>
- <pre>
- $ <b>go install github.com/user/hello</b>
- </pre>
- <p>
- 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>
- $ <b>cd $GOPATH/src/github.com/user/hello</b>
- $ <b>go install</b>
- </pre>
- <p>
- 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>
- <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>
- 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>
- Or, as you have added <code>$GOPATH/bin</code> to your <code>PATH</code>,
- just type the binary name:
- </p>
- <pre>
- $ <b>hello</b>
- Hello, world.
- </pre>
- <p>
- 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>
- $ <b>cd $GOPATH/src/github.com/user/hello</b>
- $ <b>git init</b>
- Initialized empty Git repository in /home/user/work/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>
- 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>
- Again, the first step is to choose a package path (we'll use
- <code>github.com/user/stringutil</code>) and create the package directory:
- </p>
- <pre>
- $ <b>mkdir $GOPATH/src/github.com/user/stringutil</b>
- </pre>
- <p>
- Next, create a file named <code>reverse.go</code> in that directory with the
- following contents.
- </p>
- <pre>
- // Package stringutil contains utility functions for working with strings.
- package stringutil
- // Reverse returns its argument string reversed rune-wise left to right.
- func Reverse(s string) string {
- r := []rune(s)
- for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
- r[i], r[j] = r[j], r[i]
- }
- return string(r)
- }
- </pre>
- <p>
- Now, test that the package compiles with <code>go build</code>:
- </p>
- <pre>
- $ <b>go build github.com/user/stringutil</b>
- </pre>
- <p>
- Or, if you are working in the package's source directory, just:
- </p>
- <pre>
- $ <b>go build</b>
- </pre>
- <p>
- 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>stringutil</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>
- package main
- import (
- "fmt"
- <b>"github.com/user/stringutil"</b>
- )
- func main() {
- fmt.Printf(stringutil.Reverse("!oG ,olleH"))
- }
- </pre>
- <p>
- 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>
- $ <b>go install github.com/user/hello</b>
- </pre>
- <p>
- the <code>stringutil</code> package will be installed as well, automatically.
- </p>
- <p>
- Running the new version of the program, you should see a new, reversed message:
- </p>
- <pre>
- $ <b>hello</b>
- Hello, Go!
- </pre>
- <p>
- After the steps above, your workspace should look like this:
- </p>
- <pre>
- bin/
- hello # command executable
- pkg/
- linux_amd64/ # this will reflect your OS and architecture
- github.com/user/
- stringutil.a # package object
- src/
- github.com/user/
- hello/
- hello.go # command source
- stringutil/
- reverse.go # package source
- </pre>
- <p>
- Note that <code>go install</code> placed the <code>stringutil.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>
- <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>
- 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>
- Add a test to the <code>stringutil</code> package by creating the file
- <code>$GOPATH/src/github.com/user/stringutil/reverse_test.go</code> containing
- the following Go code.
- </p>
- <pre>
- package stringutil
- import "testing"
- func TestReverse(t *testing.T) {
- cases := []struct {
- in, want string
- }{
- {"Hello, world", "dlrow ,olleH"},
- {"Hello, 世界", "界世 ,olleH"},
- {"", ""},
- }
- for _, c := range cases {
- got := Reverse(c.in)
- if got != c.want {
- t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
- }
- }
- }
- </pre>
- <p>
- Then run the test with <code>go test</code>:
- </p>
- <pre>
- $ <b>go test github.com/user/stringutil</b>
- ok github.com/user/stringutil 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>
- $ <b>go test</b>
- ok github.com/user/stringutil 0.165s
- </pre>
- <p>
- Run <code><a href="/cmd/go/#hdr-Test_packages">go help test</a></code> and see the
- <a href="/pkg/testing/">testing package documentation</a> for more detail.
- </p>
- <h2 id="remote">Remote packages</h2>
- <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> tool uses
- this property to automatically fetch packages from remote repositories.
- For instance, the examples described in this document are also kept in a
- Git repository hosted at GitHub
- <code><a href="https://github.com/golang/example">github.com/golang/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>
- $ <b>go get github.com/golang/example/hello</b>
- $ <b>$GOPATH/bin/hello</b>
- Hello, Go examples!
- </pre>
- <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>
- After issuing the above <code>go get</code> command, the workspace directory
- tree should now look like this:
- </p>
- <pre>
- bin/
- hello # command executable
- pkg/
- linux_amd64/
- github.com/golang/example/
- stringutil.a # package object
- github.com/user/
- stringutil.a # package object
- src/
- github.com/golang/example/
- .git/ # Git repository metadata
- hello/
- hello.go # command source
- stringutil/
- reverse.go # package source
- reverse_test.go # test source
- github.com/user/
- hello/
- hello.go # command source
- stringutil/
- reverse.go # package source
- reverse_test.go # test source
- </pre>
- <p>
- The <code>hello</code> command hosted at GitHub depends on the
- <code>stringutil</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 "github.com/golang/example/stringutil"
- </pre>
- <p>
- This convention is the easiest way to make your Go packages available for
- others to use.
- The <a href="//golang.org/wiki/Projects">Go Wiki</a>
- and <a href="//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> tool, see
- <code><a href="/cmd/go/#hdr-Remote_import_paths">go help importpath</a></code>.
- </p>
- <h2 id="next">What's next</h2>
- <p>
- Subscribe to the
- <a href="//groups.google.com/group/golang-announce">golang-announce</a>
- mailing list to be notified when a new stable version of Go is released.
- </p>
- <p>
- See <a href="/doc/effective_go.html">Effective Go</a> for tips on writing
- clear, idiomatic Go code.
- </p>
- <p>
- Take <a href="//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>
- <h2 id="help">Getting help</h2>
- <p>
- For real-time help, ask the helpful gophers in <code>#go-nuts</code> on the
- <a href="http://freenode.net/">Freenode</a> IRC server.
- </p>
- <p>
- The official mailing list for discussion of the Go language is
- <a href="//groups.google.com/group/golang-nuts">Go Nuts</a>.
- </p>
- <p>
- Report bugs using the
- <a href="//golang.org/issue">Go issue tracker</a>.
- </p>
|