diff options
Diffstat (limited to 'go/golang/go/doc/code.html')
-rw-r--r-- | go/golang/go/doc/code.html | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/go/golang/go/doc/code.html b/go/golang/go/doc/code.html new file mode 100644 index 00000000..b6d41ef6 --- /dev/null +++ b/go/golang/go/doc/code.html @@ -0,0 +1,648 @@ +<!--{ + "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 two directories at its root: +</p> + +<ul> +<li><code>src</code> contains Go source files, and +<li><code>bin</code> contains executable commands. +</ul> + +<p> +The <code>go</code> tool builds and installs binaries to the <code>bin</code> directory. +</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 +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> +Note that symbolic links should <b>not</b> be used to link files or directories into your 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.Println("Hello, world.") +} +</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. +Instead it saves the compiled package in the local build cache. +</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.Println(stringutil.Reverse("!oG ,olleH")) +} +</pre> + +<p> +Install the <code>hello</code> program: +</p> + +<pre> +$ <b>go install github.com/user/hello</b> +</pre> + +<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 +src/ + github.com/user/ + hello/ + hello.go # command source + stringutil/ + reverse.go # package source +</pre> + +<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 +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="https://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> |