github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2014/organizeio.slide (about) 1 Organizing Go code 2 3 David Crawshaw 4 crawshaw@golang.org 5 6 7 * Packages 8 9 * Go programs are made up of packages 10 11 All Go source is part of a package. 12 Every file begins with a package statement. 13 Programs start in package main. 14 15 .play organizeio/hello.go 16 17 For very small programs, `main` is the only package you need to write. 18 19 The hello world program _imports_ package `fmt`. 20 21 The function `Println` is defined in the fmt package. 22 23 * An example package: fmt 24 25 // Package fmt implements formatted I/O. 26 package fmt 27 28 // Println formats using the default formats for its 29 // operands and writes to standard output. 30 func Println(a ...interface{}) (n int, err error) { 31 ... 32 } 33 34 func newPrinter() *pp { 35 ... 36 } 37 38 The `Println` function is _exported_. It starts with an upper case 39 letter, which means other packages are allowed to call it. 40 41 The `newPrinter` function is _unexported_. It starts with a lower 42 case letter, so it can only be used inside the fmt package. 43 44 * The shape of a package 45 46 Packages collect related code. 47 48 They can be big or small, 49 and may be spread across multiple files. 50 51 All the files in a package live in a single directory. 52 53 The `net/http` package exports more than 100 names. (18 files) 54 The `errors` package exports just one. (1 file) 55 56 * The name of a package 57 58 Keep package names short and meaningful. 59 Don't use underscores, they make package names long. 60 61 - `io/ioutil` not `io/util` 62 - `suffixarray` not `suffix_array` 63 64 Don't overgeneralize. A `util` package could be anything. 65 66 The name of a package is part of its type and function names. 67 On its own, type `Buffer` is ambiguous. But users see: 68 69 buf := new(bytes.Buffer) 70 71 Choose package names carefully. 72 73 Choose good names for users. 74 75 * The testing of a package 76 77 Tests are distinguished by file name. Test files end in `_test.go`. 78 79 package fmt 80 81 import "testing" 82 83 var fmtTests = []fmtTest{ 84 {"%d", 12345, "12345"}, 85 {"%v", 12345, "12345"}, 86 {"%t", true, "true"}, 87 } 88 89 func TestSprintf(t *testing.T) { 90 for _, tt := range fmtTests { 91 if s := Sprintf(tt.fmt, tt.val); s != tt.out { 92 t.Errorf("...") 93 } 94 } 95 } 96 97 Test well. 98 99 * Code organization 100 101 * Introducing workspaces 102 103 Your Go code is kept in a _workspace_. 104 105 A workspace contains _many_ source repositories (git, hg). 106 107 The Go tool understands the layout of a workspace. 108 You don't need a `Makefile`. The file layout is everything. 109 110 Change the file layout, change the build. 111 112 $GOPATH/ 113 src/ 114 github.com/user/repo/ 115 mypkg/ 116 mysrc1.go 117 mysrc2.go 118 cmd/mycmd/ 119 main.go 120 bin/ 121 mycmd 122 123 124 * Let's make a workspace 125 126 mkdir /tmp/gows 127 GOPATH=/tmp/gows 128 129 The `GOPATH` environment variable tells the Go tool where your workspace is located. 130 131 go get github.com/dsymonds/fixhub/cmd/fixhub 132 133 The `go` `get` command fetches source repositories from the internet and places them in your workspace. 134 135 Package paths matter to the Go tool. Using "github.com/..." 136 means the tool knows how to fetch your repository. 137 138 go install github.com/dsymonds/fixhub/cmd/fixhub 139 140 The go install command builds a binary and places it in `$GOPATH/bin/fixhub`. 141 142 * Our workspace 143 144 $GOPATH/ 145 bin/fixhub # installed binary 146 pkg/darwin_amd64/ # compiled archives 147 code.google.com/p/goauth2/oauth.a 148 github.com/... 149 src/ # source repositories 150 code.google.com/p/goauth2/ 151 .hg 152 oauth # used by package go-github 153 ... 154 github.com/ 155 golang/lint/... # used by package fixhub 156 .git 157 google/go-github/... # used by package fixhub 158 .git 159 dsymonds/fixhub/ 160 .git 161 client.go 162 cmd/fixhub/fixhub.go # package main 163 164 `go` `get` fetched many repositories. 165 `go` `install` built a binary out of them. 166 167 168 * Why prescribe file layout? 169 170 Using file layout for builds means less configuration. 171 In fact, it means no configuration. 172 No `Makefile`, no `build.xml`. 173 174 Less time configuring means more time programming. 175 176 Everyone in the community uses the same layout. 177 This makes it easier to share code. 178 179 The Go tool helps build the Go community. 180 181 * Where's your workspace? 182 183 It is possible to have multiple workspaces, but most people just use one. 184 185 So where do you point your `GOPATH`? A common preference: 186 187 .image organizeio/home.png 188 189 This puts `src`, `bin`, and `pkg` directories in your home directory. 190 191 (Convenient, because `$HOME/bin` is probably already in your `PATH`.) 192 193 194 * Working with workspaces 195 196 Unix eschews typing: 197 198 CDPATH=$GOPATH/src/github.com:$GOPATH/src/code.google.com/p 199 200 $ cd dsymonds/fixhub 201 /tmp/gows/src/github.com/dsymonds/fixhub 202 $ cd goauth2 203 /tmp/gows/src/code.google.com/p/goauth2 204 $ 205 206 A shell function for your `~/.profile`: 207 208 gocd () { cd `go list -f '{{.Dir}}' $1` } 209 210 This lets you move around using the Go tool's path names: 211 212 $ gocd .../lint 213 /tmp/gows/src/github.com/golang/lint 214 $ 215 216 217 * The Go tool's many talents 218 219 $ go help 220 Go is a tool for managing Go source code. 221 222 Usage: 223 224 go command [arguments] 225 226 The commands are: 227 228 Worth exploring! Some highlights: 229 230 build compile packages and dependencies 231 get download and install packages and dependencies 232 install compile and install packages and dependencies 233 test test packages 234 235 There are more useful subcommands. Check out `vet` and `fmt`. 236 237 * Dependency management 238 239 * In production, versions matter. 240 241 `go` `get` always fetches the latest code, even if your build breaks. 242 243 .image organizeio/gogetversion.png 244 245 That's fine when developing. It's not fine when releasing. 246 We need other tools. 247 248 * Versioning 249 250 My favorite technique: vendoring. 251 252 For building binaries, import the packages you care about 253 into a `_vendor` workspace. 254 255 GOPATH=/tmp/gows/_vendor:/tmp/gows 256 257 For building libraries, import the packages you care about 258 into your repository. Rename the imports to: 259 260 import "github.com/you/proj/vendor/github.com/them/lib" 261 262 Long paths, but trivial to automate. Write a Go program! 263 264 Another technique: [[http://gopkg.in][gopkg.in]], provides versioned package paths: 265 266 gopkg.in/user/pkg.v3 -> github.com/user/pkg (branch/tag v3, v3.N, or v.3.N.M) 267 268 * Naming 269 270 * Names matter 271 272 Programs are full of names. Names have costs and benefits. 273 274 *Costs*: *space* *and* *time* 275 Names need to be in short term memory when reading code. 276 You can only fit so many. Longer names take up more space. 277 278 *Benefits:* *information* 279 A good name is not only a referent, it conveys information. 280 281 Use the shortest name that carries the right amount of information in its context. 282 283 Devote time to naming. 284 285 * Name style 286 287 Use `camelCase`, `not_underscores`. 288 Local variable names should be short, typically one or two characters. 289 290 Package names are usually one lowercase word. 291 292 Global variables should have longer names. 293 294 Don't stutter. 295 296 - `bytes.Buffer` not `bytes.ByteBuffer` 297 - `zip.Reader` not `zip.ZipReader` 298 - `errors.New` not `errors.NewError` 299 - `r` not `bytesReader` 300 - `i` not `loopIterator` 301 302 * Doc comments 303 304 Doc comments precede the declaration of an exported identifier: 305 306 // Join concatenates the elements of elem to create a single string. 307 // The separator string sep is placed between elements in the resulting string. 308 func Join(elem []string, sep string) string { 309 310 The godoc tool extracts such comments and presents them on the web: 311 312 .image organizeio/godoc.png 313 314 * Writing doc comments 315 316 Doc comments should be English sentences and paragraphs. 317 They use no special formatting beyond indentation for preformatted text. 318 319 Doc comments should begin with the noun they describe. 320 321 // Join concatenates… good 322 // This function… bad 323 324 Package docs go above the package declaration: 325 326 // Package fmt… 327 package fmt 328 329 Read the world's Go docs on [[godoc.org]]. E.g. 330 331 [[http://godoc.org/code.google.com/p/go.tools/cmd/vet]] 332 333 * Questions?