github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/doc/code.html (about) 1 <!--{ 2 "Title": "How to Write Go Code" 3 }--> 4 5 <h2 id="Introduction">Introduction</h2> 6 7 <p> 8 This document demonstrates the development of a simple Go package and 9 introduces the <a href="/cmd/go/">go tool</a>, the standard way to fetch, 10 build, and install Go packages and commands. 11 </p> 12 13 <p> 14 The <code>go</code> tool requires you to organize your code in a specific 15 way. Please read this document carefully. 16 It explains the simplest way to get up and running with your Go installation. 17 </p> 18 19 <p> 20 A 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> 30 The <code>go</code> tool is designed to work with open source code maintained 31 in public repositories. Although you don't need to publish your code, the model 32 for how the environment is set up works the same whether you do or not. 33 </p> 34 35 <p> 36 Go code must be kept inside a <i>workspace</i>. 37 A 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> 47 The <code>go</code> tool builds source packages and installs the resulting 48 binaries to the <code>pkg</code> and <code>bin</code> directories. 49 </p> 50 51 <p> 52 The <code>src</code> subdirectory typically contains multiple version control 53 repositories (such as for Git or Mercurial) that track the development of one 54 or more source packages. 55 </p> 56 57 <p> 58 To give you an idea of how a workspace looks in practice, here's an example: 59 </p> 60 61 <pre> 62 bin/ 63 hello # command executable 64 outyet # command executable 65 pkg/ 66 linux_amd64/ 67 github.com/golang/example/ 68 stringutil.a # package object 69 src/ 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> 83 This workspace contains one repository (<code>example</code>) 84 comprising two commands (<code>hello</code> and <code>outyet</code>) 85 and one library (<code>stringutil</code>). 86 </p> 87 88 <p> 89 A typical workspace would contain many source repositories containing many 90 packages and commands. Most Go programmers keep <i>all</i> their Go source code 91 and dependencies in a single workspace. 92 </p> 93 94 <p> 95 Commands and libraries are built from different kinds of source packages. 96 We 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> 103 The <code>GOPATH</code> environment variable specifies the location of your 104 workspace. It is likely the only environment variable you'll need to set 105 when developing Go code. 106 </p> 107 108 <p> 109 To get started, create a workspace directory and set <code>GOPATH</code> 110 accordingly. 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 112 same 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> 121 For convenience, add the workspace's <code>bin</code> subdirectory 122 to 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> 133 The packages from the standard library are given short paths such as 134 <code>"fmt"</code> and <code>"net/http"</code>. 135 For your own packages, you must choose a base path that is unlikely to 136 collide with future additions to the standard library or other external 137 libraries. 138 </p> 139 140 <p> 141 If you keep your code in a source repository somewhere, then you should use the 142 root of that source repository as your base path. 143 For 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> 148 Note that you don't need to publish your code to a remote repository before you 149 can build it. It's just a good habit to organize your code as if you will 150 publish it someday. In practice you can choose any arbitrary path name, 151 as long as it is unique to the standard library and greater Go ecosystem. 152 </p> 153 154 <p> 155 We'll use <code>github.com/user</code> as our base path. Create a directory 156 inside 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> 167 To 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 169 inside your workspace: 170 </p> 171 172 <pre> 173 $ <b>mkdir $GOPATH/src/github.com/user/hello</b> 174 </pre> 175 176 <p> 177 Next, create a file named <code>hello.go</code> inside that directory, 178 containing the following Go code. 179 </p> 180 181 <pre> 182 package main 183 184 import "fmt" 185 186 func main() { 187 fmt.Printf("Hello, world.\n") 188 } 189 </pre> 190 191 <p> 192 Now 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> 200 Note 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> 207 You can also omit the package path if you run <code>go install</code> from the 208 package 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> 217 This command builds the <code>hello</code> command, producing an executable 218 binary. It then installs that binary to the workspace's <code>bin</code> 219 directory as <code>hello</code> (or, under Windows, <code>hello.exe</code>). 220 In our example, that will be <code>$GOPATH/bin/hello</code>, which is 221 <code>$HOME/go/bin/hello</code>. 222 </p> 223 224 <p> 225 The <code>go</code> tool will only print output when an error occurs, so if 226 these commands produce no output they have executed successfully. 227 </p> 228 229 <p> 230 You 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> 235 Hello, world. 236 </pre> 237 238 <p> 239 Or, as you have added <code>$GOPATH/bin</code> to your <code>PATH</code>, 240 just type the binary name: 241 </p> 242 243 <pre> 244 $ <b>hello</b> 245 Hello, world. 246 </pre> 247 248 <p> 249 If you're using a source control system, now would be a good time to initialize 250 a repository, add the files, and commit your first change. Again, this step is 251 optional: 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> 257 Initialized 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> 266 Pushing 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> 273 Let's write a library and use it from the <code>hello</code> program. 274 </p> 275 276 <p> 277 Again, 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> 286 Next, create a file named <code>reverse.go</code> in that directory with the 287 following contents. 288 </p> 289 290 <pre> 291 // Package stringutil contains utility functions for working with strings. 292 package stringutil 293 294 // Reverse returns its argument string reversed rune-wise left to right. 295 func Reverse(s string) string { 296 r := []rune(s) 297 for i, j := 0, len(r)-1; i < 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> 305 Now, 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> 313 Or, 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> 321 This won't produce an output file. To do that, you must use <code>go 322 install</code>, which places the package object inside the <code>pkg</code> 323 directory of the workspace. 324 </p> 325 326 <p> 327 After confirming that the <code>stringutil</code> package builds, 328 modify 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> 333 package main 334 335 import ( 336 "fmt" 337 338 <b>"github.com/user/stringutil"</b> 339 ) 340 341 func main() { 342 fmt.Printf(stringutil.Reverse("!oG ,olleH")) 343 } 344 </pre> 345 346 <p> 347 Whenever the <code>go</code> tool installs a package or binary, it also 348 installs whatever dependencies it has. 349 So 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> 357 the <code>stringutil</code> package will be installed as well, automatically. 358 </p> 359 360 <p> 361 Running the new version of the program, you should see a new, reversed message: 362 </p> 363 364 <pre> 365 $ <b>hello</b> 366 Hello, Go! 367 </pre> 368 369 <p> 370 After the steps above, your workspace should look like this: 371 </p> 372 373 <pre> 374 bin/ 375 hello # command executable 376 pkg/ 377 linux_amd64/ # this will reflect your OS and architecture 378 github.com/user/ 379 stringutil.a # package object 380 src/ 381 github.com/user/ 382 hello/ 383 hello.go # command source 384 stringutil/ 385 reverse.go # package source 386 </pre> 387 388 <p> 389 Note that <code>go install</code> placed the <code>stringutil.a</code> object 390 in a directory inside <code>pkg/linux_amd64</code> that mirrors its source 391 directory. 392 This is so that future invocations of the <code>go</code> tool can find the 393 package object and avoid recompiling the package unnecessarily. 394 The <code>linux_amd64</code> part is there to aid in cross-compilation, 395 and will reflect the operating system and architecture of your system. 396 </p> 397 398 <p> 399 Go command executables are statically linked; the package objects need not 400 be present to run Go programs. 401 </p> 402 403 404 <h3 id="PackageNames">Package names</h3> 405 406 <p> 407 The first statement in a Go source file must be 408 </p> 409 410 <pre> 411 package <i>name</i> 412 </pre> 413 414 <p> 415 where <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> 420 Go's convention is that the package name is the last element of the 421 import path: the package imported as "<code>crypto/rot13</code>" 422 should be named <code>rot13</code>. 423 </p> 424 425 <p> 426 Executable commands must always use <code>package main</code>. 427 </p> 428 429 <p> 430 There is no requirement that package names be unique 431 across all packages linked into a single binary, 432 only that the import paths (their full file names) be unique. 433 </p> 434 435 <p> 436 See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about 437 Go's naming conventions. 438 </p> 439 440 441 <h2 id="Testing">Testing</h2> 442 443 <p> 444 Go has a lightweight test framework composed of the <code>go test</code> 445 command and the <code>testing</code> package. 446 </p> 447 448 <p> 449 You write a test by creating a file with a name ending in <code>_test.go</code> 450 that contains functions named <code>TestXXX</code> with signature 451 <code>func (t *testing.T)</code>. 452 The test framework runs each such function; 453 if 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> 458 Add 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 460 the following Go code. 461 </p> 462 463 <pre> 464 package stringutil 465 466 import "testing" 467 468 func 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> 486 Then run the test with <code>go test</code>: 487 </p> 488 489 <pre> 490 $ <b>go test github.com/user/stringutil</b> 491 ok github.com/user/stringutil 0.165s 492 </pre> 493 494 <p> 495 As always, if you are running the <code>go</code> tool from the package 496 directory, you can omit the package path: 497 </p> 498 499 <pre> 500 $ <b>go test</b> 501 ok github.com/user/stringutil 0.165s 502 </pre> 503 504 <p> 505 Run <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> 513 An import path can describe how to obtain the package source code using a 514 revision control system such as Git or Mercurial. The <code>go</code> tool uses 515 this property to automatically fetch packages from remote repositories. 516 For instance, the examples described in this document are also kept in a 517 Git repository hosted at GitHub 518 <code><a href="https://github.com/golang/example">github.com/golang/example</a></code>. 519 If 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> 526 Hello, Go examples! 527 </pre> 528 529 <p> 530 If the specified package is not present in a workspace, <code>go get</code> 531 will 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 533 fetch and behaves the same as <code>go install</code>.) 534 </p> 535 536 <p> 537 After issuing the above <code>go get</code> command, the workspace directory 538 tree should now look like this: 539 </p> 540 541 <pre> 542 bin/ 543 hello # command executable 544 pkg/ 545 linux_amd64/ 546 github.com/golang/example/ 547 stringutil.a # package object 548 github.com/user/ 549 stringutil.a # package object 550 src/ 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> 567 The <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 571 package, too. 572 </p> 573 574 <pre> 575 import "github.com/golang/example/stringutil" 576 </pre> 577 578 <p> 579 This convention is the easiest way to make your Go packages available for 580 others to use. 581 The <a href="//golang.org/wiki/Projects">Go Wiki</a> 582 and <a href="//godoc.org/">godoc.org</a> 583 provide lists of external Go projects. 584 </p> 585 586 <p> 587 For 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> 595 Subscribe to the 596 <a href="//groups.google.com/group/golang-announce">golang-announce</a> 597 mailing list to be notified when a new stable version of Go is released. 598 </p> 599 600 <p> 601 See <a href="/doc/effective_go.html">Effective Go</a> for tips on writing 602 clear, idiomatic Go code. 603 </p> 604 605 <p> 606 Take <a href="//tour.golang.org/">A Tour of Go</a> to learn the language 607 proper. 608 </p> 609 610 <p> 611 Visit the <a href="/doc/#articles">documentation page</a> for a set of in-depth 612 articles about the Go language and its libraries and tools. 613 </p> 614 615 616 <h2 id="help">Getting help</h2> 617 618 <p> 619 For 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> 624 The 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> 629 Report bugs using the 630 <a href="//golang.org/issue">Go issue tracker</a>. 631 </p>