blob: 8cbfba04a02254a3b2def61c19463bb36a28b023 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001<!--{
2 "Title": "How to Write Go Code"
3}-->
4
5<h2 id="Introduction">Introduction</h2>
6
7<p>
8This document demonstrates the development of a simple Go package and
9introduces the <a href="/cmd/go/">go tool</a>, the standard way to fetch,
10build, and install Go packages and commands.
11</p>
12
13<p>
14The <code>go</code> tool requires you to organize your code in a specific
15way. Please read this document carefully.
16It explains the simplest way to get up and running with your Go installation.
17</p>
18
19<p>
20A similar explanation is available as a
21<a href="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>.
22</p>
23
24
25<h2 id="Organization">Code organization</h2>
26
27<h3 id="Workspaces">Workspaces</h3>
28
29<p>
30The <code>go</code> tool is designed to work with open source code maintained
31in public repositories. Although you don't need to publish your code, the model
32for how the environment is set up works the same whether you do or not.
33</p>
34
35<p>
36Go code must be kept inside a <i>workspace</i>.
37A workspace is a directory hierarchy with three directories at its root:
38</p>
39
40<ul>
41<li><code>src</code> contains Go source files organized into packages (one package per directory),
42<li><code>pkg</code> contains package objects, and
43<li><code>bin</code> contains executable commands.
44</ul>
45
46<p>
47The <code>go</code> tool builds source packages and installs the resulting
48binaries to the <code>pkg</code> and <code>bin</code> directories.
49</p>
50
51<p>
52The <code>src</code> subdirectory typically contains multiple version control
53repositories (such as for Git or Mercurial) that track the development of one
54or more source packages.
55</p>
56
57<p>
58To give you an idea of how a workspace looks in practice, here's an example:
59</p>
60
61<pre>
62bin/
63 hello # command executable
64 outyet # command executable
65pkg/
66 linux_amd64/
67 github.com/golang/example/
68 stringutil.a # package object
69src/
70 <a href="https://github.com/golang/example/">github.com/golang/example/</a>
71 .git/ # Git repository metadata
72 hello/
73 hello.go # command source
74 outyet/
75 main.go # command source
76 main_test.go # test source
77 stringutil/
78 reverse.go # package source
79 reverse_test.go # test source
80</pre>
81
82<p>
83This workspace contains one repository (<code>example</code>)
84comprising two commands (<code>hello</code> and <code>outyet</code>)
85and one library (<code>stringutil</code>).
86</p>
87
88<p>
89A typical workspace would contain many source repositories containing many
90packages and commands. Most Go programmers keep <i>all</i> their Go source code
91and dependencies in a single workspace.
92</p>
93
94<p>
95Commands and libraries are built from different kinds of source packages.
96We will discuss the distinction <a href="#PackageNames">later</a>.
97</p>
98
99
100<h3 id="GOPATH">The <code>GOPATH</code> environment variable</h3>
101
102<p>
103The <code>GOPATH</code> environment variable specifies the location of your
104workspace. It is likely the only environment variable you'll need to set
105when developing Go code.
106</p>
107
108<p>
109To get started, create a workspace directory and set <code>GOPATH</code>
110accordingly. Your workspace can be located wherever you like, but we'll use
Dan Willemsen6ff23252015-09-15 13:49:18 -0700111<code>$HOME/work</code> in this document. Note that this must <b>not</b> be the
Colin Cross7bb052a2015-02-03 12:59:37 -0800112same path as your Go installation.
Dan Willemsen6ff23252015-09-15 13:49:18 -0700113(Another common setup is to set <code>GOPATH=$HOME</code>.)
Colin Cross7bb052a2015-02-03 12:59:37 -0800114</p>
115
116<pre>
Dan Willemsen6ff23252015-09-15 13:49:18 -0700117$ <b>mkdir $HOME/work</b>
118$ <b>export GOPATH=$HOME/work</b>
Colin Cross7bb052a2015-02-03 12:59:37 -0800119</pre>
120
121<p>
122For convenience, add the workspace's <code>bin</code> subdirectory
123to your <code>PATH</code>:
124</p>
125
126<pre>
127$ <b>export PATH=$PATH:$GOPATH/bin</b>
128</pre>
129
Dan Willemsen6ff23252015-09-15 13:49:18 -0700130<p>
131To learn more about setting up the <code>GOPATH</code> environment variable,
132please see
133<a href="/cmd/go/#hdr-GOPATH_environment_variable"><code>go help gopath</code></a>
134</p>
Colin Cross7bb052a2015-02-03 12:59:37 -0800135
136<h3 id="PackagePaths">Package paths</h3>
137
138<p>
139The packages from the standard library are given short paths such as
140<code>"fmt"</code> and <code>"net/http"</code>.
141For your own packages, you must choose a base path that is unlikely to
142collide with future additions to the standard library or other external
143libraries.
144</p>
145
146<p>
147If you keep your code in a source repository somewhere, then you should use the
148root of that source repository as your base path.
149For instance, if you have a <a href="https://github.com/">GitHub</a> account at
150<code>github.com/user</code>, that should be your base path.
151</p>
152
153<p>
154Note that you don't need to publish your code to a remote repository before you
155can build it. It's just a good habit to organize your code as if you will
156publish it someday. In practice you can choose any arbitrary path name,
157as long as it is unique to the standard library and greater Go ecosystem.
158</p>
159
160<p>
161We'll use <code>github.com/user</code> as our base path. Create a directory
162inside your workspace in which to keep source code:
163</p>
164
165<pre>
166$ <b>mkdir -p $GOPATH/src/github.com/user</b>
167</pre>
168
169
170<h3 id="Command">Your first program</h3>
171
172<p>
173To compile and run a simple program, first choose a package path (we'll use
174<code>github.com/user/hello</code>) and create a corresponding package directory
175inside your workspace:
176</p>
177
178<pre>
179$ <b>mkdir $GOPATH/src/github.com/user/hello</b>
180</pre>
181
182<p>
183Next, create a file named <code>hello.go</code> inside that directory,
184containing the following Go code.
185</p>
186
187<pre>
188package main
189
190import "fmt"
191
192func main() {
193 fmt.Printf("Hello, world.\n")
194}
195</pre>
196
197<p>
198Now you can build and install that program with the <code>go</code> tool:
199</p>
200
201<pre>
202$ <b>go install github.com/user/hello</b>
203</pre>
204
205<p>
206Note that you can run this command from anywhere on your system. The
207<code>go</code> tool finds the source code by looking for the
208<code>github.com/user/hello</code> package inside the workspace specified by
209<code>GOPATH</code>.
210</p>
211
212<p>
213You can also omit the package path if you run <code>go install</code> from the
214package directory:
215</p>
216
217<pre>
218$ <b>cd $GOPATH/src/github.com/user/hello</b>
219$ <b>go install</b>
220</pre>
221
222<p>
223This command builds the <code>hello</code> command, producing an executable
224binary. It then installs that binary to the workspace's <code>bin</code>
225directory as <code>hello</code> (or, under Windows, <code>hello.exe</code>).
226In our example, that will be <code>$GOPATH/bin/hello</code>, which is
Dan Willemsen6ff23252015-09-15 13:49:18 -0700227<code>$HOME/work/bin/hello</code>.
Colin Cross7bb052a2015-02-03 12:59:37 -0800228</p>
229
230<p>
231The <code>go</code> tool will only print output when an error occurs, so if
232these commands produce no output they have executed successfully.
233</p>
234
235<p>
236You can now run the program by typing its full path at the command line:
237</p>
238
239<pre>
240$ <b>$GOPATH/bin/hello</b>
241Hello, world.
242</pre>
243
244<p>
245Or, as you have added <code>$GOPATH/bin</code> to your <code>PATH</code>,
246just type the binary name:
247</p>
248
249<pre>
250$ <b>hello</b>
251Hello, world.
252</pre>
253
254<p>
255If you're using a source control system, now would be a good time to initialize
256a repository, add the files, and commit your first change. Again, this step is
257optional: you do not need to use source control to write Go code.
258</p>
259
260<pre>
261$ <b>cd $GOPATH/src/github.com/user/hello</b>
262$ <b>git init</b>
Dan Willemsen6ff23252015-09-15 13:49:18 -0700263Initialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/
Colin Cross7bb052a2015-02-03 12:59:37 -0800264$ <b>git add hello.go</b>
265$ <b>git commit -m "initial commit"</b>
266[master (root-commit) 0b4507d] initial commit
267 1 file changed, 1 insertion(+)
268 create mode 100644 hello.go
269</pre>
270
271<p>
272Pushing the code to a remote repository is left as an exercise for the reader.
273</p>
274
275
276<h3 id="Library">Your first library</h3>
277
278<p>
279Let's write a library and use it from the <code>hello</code> program.
280</p>
281
282<p>
283Again, the first step is to choose a package path (we'll use
284<code>github.com/user/stringutil</code>) and create the package directory:
285</p>
286
287<pre>
288$ <b>mkdir $GOPATH/src/github.com/user/stringutil</b>
289</pre>
290
291<p>
292Next, create a file named <code>reverse.go</code> in that directory with the
293following contents.
294</p>
295
296<pre>
297// Package stringutil contains utility functions for working with strings.
298package stringutil
299
300// Reverse returns its argument string reversed rune-wise left to right.
301func Reverse(s string) string {
302 r := []rune(s)
303 for i, j := 0, len(r)-1; i &lt; len(r)/2; i, j = i+1, j-1 {
304 r[i], r[j] = r[j], r[i]
305 }
306 return string(r)
307}
308</pre>
309
310<p>
311Now, test that the package compiles with <code>go build</code>:
312</p>
313
314<pre>
315$ <b>go build github.com/user/stringutil</b>
316</pre>
317
318<p>
319Or, if you are working in the package's source directory, just:
320</p>
321
322<pre>
323$ <b>go build</b>
324</pre>
325
326<p>
327This won't produce an output file. To do that, you must use <code>go
328install</code>, which places the package object inside the <code>pkg</code>
329directory of the workspace.
330</p>
331
332<p>
333After confirming that the <code>stringutil</code> package builds,
334modify your original <code>hello.go</code> (which is in
335<code>$GOPATH/src/github.com/user/hello</code>) to use it:
336</p>
337
338<pre>
339package main
340
341import (
342 "fmt"
343
344 <b>"github.com/user/stringutil"</b>
345)
346
347func main() {
348 fmt.Printf(stringutil.Reverse("!oG ,olleH"))
349}
350</pre>
351
352<p>
353Whenever the <code>go</code> tool installs a package or binary, it also
354installs whatever dependencies it has.
355So when you install the <code>hello</code> program
356</p>
357
358<pre>
359$ <b>go install github.com/user/hello</b>
360</pre>
361
362<p>
363the <code>stringutil</code> package will be installed as well, automatically.
364</p>
365
366<p>
367Running the new version of the program, you should see a new, reversed message:
368</p>
369
370<pre>
371$ <b>hello</b>
372Hello, Go!
373</pre>
374
375<p>
376After the steps above, your workspace should look like this:
377</p>
378
379<pre>
380bin/
381 hello # command executable
382pkg/
383 linux_amd64/ # this will reflect your OS and architecture
384 github.com/user/
385 stringutil.a # package object
386src/
387 github.com/user/
388 hello/
389 hello.go # command source
390 stringutil/
391 reverse.go # package source
392</pre>
393
394<p>
395Note that <code>go install</code> placed the <code>stringutil.a</code> object
396in a directory inside <code>pkg/linux_amd64</code> that mirrors its source
397directory.
398This is so that future invocations of the <code>go</code> tool can find the
399package object and avoid recompiling the package unnecessarily.
400The <code>linux_amd64</code> part is there to aid in cross-compilation,
401and will reflect the operating system and architecture of your system.
402</p>
403
404<p>
405Go command executables are statically linked; the package objects need not
406be present to run Go programs.
407</p>
408
409
410<h3 id="PackageNames">Package names</h3>
411
412<p>
413The first statement in a Go source file must be
414</p>
415
416<pre>
417package <i>name</i>
418</pre>
419
420<p>
421where <code><i>name</i></code> is the package's default name for imports.
422(All files in a package must use the same <code><i>name</i></code>.)
423</p>
424
425<p>
426Go's convention is that the package name is the last element of the
427import path: the package imported as "<code>crypto/rot13</code>"
428should be named <code>rot13</code>.
429</p>
430
431<p>
432Executable commands must always use <code>package main</code>.
433</p>
434
435<p>
436There is no requirement that package names be unique
437across all packages linked into a single binary,
438only that the import paths (their full file names) be unique.
439</p>
440
441<p>
442See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about
443Go's naming conventions.
444</p>
445
446
447<h2 id="Testing">Testing</h2>
448
449<p>
450Go has a lightweight test framework composed of the <code>go test</code>
451command and the <code>testing</code> package.
452</p>
453
454<p>
455You write a test by creating a file with a name ending in <code>_test.go</code>
456that contains functions named <code>TestXXX</code> with signature
457<code>func (t *testing.T)</code>.
458The test framework runs each such function;
459if the function calls a failure function such as <code>t.Error</code> or
460<code>t.Fail</code>, the test is considered to have failed.
461</p>
462
463<p>
464Add a test to the <code>stringutil</code> package by creating the file
465<code>$GOPATH/src/github.com/user/stringutil/reverse_test.go</code> containing
466the following Go code.
467</p>
468
469<pre>
470package stringutil
471
472import "testing"
473
474func TestReverse(t *testing.T) {
475 cases := []struct {
476 in, want string
477 }{
478 {"Hello, world", "dlrow ,olleH"},
479 {"Hello, 世界", "界世 ,olleH"},
480 {"", ""},
481 }
482 for _, c := range cases {
483 got := Reverse(c.in)
484 if got != c.want {
485 t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
486 }
487 }
488}
489</pre>
490
491<p>
492Then run the test with <code>go test</code>:
493</p>
494
495<pre>
496$ <b>go test github.com/user/stringutil</b>
497ok github.com/user/stringutil 0.165s
498</pre>
499
500<p>
501As always, if you are running the <code>go</code> tool from the package
502directory, you can omit the package path:
503</p>
504
505<pre>
506$ <b>go test</b>
507ok github.com/user/stringutil 0.165s
508</pre>
509
510<p>
511Run <code><a href="/cmd/go/#hdr-Test_packages">go help test</a></code> and see the
512<a href="/pkg/testing/">testing package documentation</a> for more detail.
513</p>
514
515
516<h2 id="remote">Remote packages</h2>
517
518<p>
519An import path can describe how to obtain the package source code using a
520revision control system such as Git or Mercurial. The <code>go</code> tool uses
521this property to automatically fetch packages from remote repositories.
522For instance, the examples described in this document are also kept in a
523Git repository hosted at GitHub
524<code><a href="https://github.com/golang/example">github.com/golang/example</a></code>.
525If you include the repository URL in the package's import path,
526<code>go get</code> will fetch, build, and install it automatically:
527</p>
528
529<pre>
530$ <b>go get github.com/golang/example/hello</b>
531$ <b>$GOPATH/bin/hello</b>
532Hello, Go examples!
533</pre>
534
535<p>
536If the specified package is not present in a workspace, <code>go get</code>
537will place it inside the first workspace specified by <code>GOPATH</code>.
538(If the package does already exist, <code>go get</code> skips the remote
539fetch and behaves the same as <code>go install</code>.)
540</p>
541
542<p>
543After issuing the above <code>go get</code> command, the workspace directory
544tree should now look like this:
545</p>
546
547<pre>
548bin/
549 hello # command executable
550pkg/
551 linux_amd64/
552 github.com/golang/example/
553 stringutil.a # package object
554 github.com/user/
555 stringutil.a # package object
556src/
557 github.com/golang/example/
558 .git/ # Git repository metadata
559 hello/
560 hello.go # command source
561 stringutil/
562 reverse.go # package source
563 reverse_test.go # test source
564 github.com/user/
565 hello/
566 hello.go # command source
567 stringutil/
568 reverse.go # package source
569 reverse_test.go # test source
570</pre>
571
572<p>
573The <code>hello</code> command hosted at GitHub depends on the
574<code>stringutil</code> package within the same repository. The imports in
575<code>hello.go</code> file use the same import path convention, so the
576<code>go get</code> command is able to locate and install the dependent
577package, too.
578</p>
579
580<pre>
581import "github.com/golang/example/stringutil"
582</pre>
583
584<p>
585This convention is the easiest way to make your Go packages available for
586others to use.
587The <a href="//golang.org/wiki/Projects">Go Wiki</a>
588and <a href="//godoc.org/">godoc.org</a>
589provide lists of external Go projects.
590</p>
591
592<p>
593For more information on using remote repositories with the <code>go</code> tool, see
594<code><a href="/cmd/go/#hdr-Remote_import_paths">go help importpath</a></code>.
595</p>
596
597
598<h2 id="next">What's next</h2>
599
600<p>
601Subscribe to the
602<a href="//groups.google.com/group/golang-announce">golang-announce</a>
603mailing list to be notified when a new stable version of Go is released.
604</p>
605
606<p>
607See <a href="/doc/effective_go.html">Effective Go</a> for tips on writing
608clear, idiomatic Go code.
609</p>
610
611<p>
612Take <a href="//tour.golang.org/">A Tour of Go</a> to learn the language
613proper.
614</p>
615
616<p>
617Visit the <a href="/doc/#articles">documentation page</a> for a set of in-depth
618articles about the Go language and its libraries and tools.
619</p>
620
621
622<h2 id="help">Getting help</h2>
623
624<p>
625For real-time help, ask the helpful gophers in <code>#go-nuts</code> on the
626<a href="http://freenode.net/">Freenode</a> IRC server.
627</p>
628
629<p>
630The official mailing list for discussion of the Go language is
631<a href="//groups.google.com/group/golang-nuts">Go Nuts</a>.
632</p>
633
634<p>
635Report bugs using the
636<a href="//golang.org/issue">Go issue tracker</a>.
637</p>