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