mirror of
https://github.com/golang/go
synced 2024-11-26 16:46:58 -07:00
doc: remove code.html
This is being moved to x/website in https://golang.org/cl/199058. Updates golang/go#33637 Updates golang/go#29206 Change-Id: I5c58b784fcdd212d7a003cd0f4085059f33a47c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/199057 Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
This commit is contained in:
parent
961837dec2
commit
60dc159cf7
643
doc/code.html
643
doc/code.html
@ -1,643 +0,0 @@
|
||||
<!--{
|
||||
"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>
|
||||
|
||||
<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/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, 7 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>
|
Loading…
Reference in New Issue
Block a user