github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2014/names.slide (about) 1 What's in a name? 2 October 2014 3 4 Andrew Gerrand 5 Google Inc. 6 adg@golang.org 7 @enneff 8 https://golang.org/ 9 10 11 * An old joke 12 13 14 * Names matter 15 16 Readability is the defining quality of good code. 17 18 Good names are critical to readability. 19 20 This talk is about naming in Go. 21 22 23 * Good names 24 25 A good name is: 26 27 - Consistent (easy to guess), 28 - Short (easy to type), 29 - Accurate (easy to understand). 30 31 32 * A rule of thumb 33 34 The greater the distance between a name's declaration and its uses, 35 the longer the name should be. 36 37 38 * Use MixedCase 39 40 Names in Go should use `MixedCase`. 41 42 (Don't use `names_with_underscores`.) 43 44 Acronyms should be all capitals, as in `ServeHTTP` and `IDProcessor`. 45 46 47 * Local variables 48 49 Keep them short; long names obscure what the code _does_. 50 51 Prefer `i` to `index`. 52 Prefer `r` to `reader`. 53 54 Longer names may help in long functions, or functions with many local variables. 55 56 (But often this just means you should refactor.) 57 58 59 * Bad 60 61 func RuneCount(buffer []byte) int { 62 index, count := 0, 0 63 for index < len(buffer) { 64 if buffer[index] < RuneSelf { 65 index++ 66 } else { 67 _, size := DecodeRune(buffer[index:]) 68 index += size 69 } 70 count++ 71 } 72 return count 73 } 74 75 76 * Good 77 78 func RuneCount(b []byte) int { 79 i, n := 0, 0 80 for i < len(b) { 81 if b[i] < RuneSelf { 82 i++ 83 } else { 84 _, size := DecodeRune(b[i:]) 85 i += size 86 } 87 n++ 88 } 89 return n 90 } 91 92 93 * Parameters 94 95 Function parameters are like local variables, 96 but they also serve as documentation. 97 98 Where the types are descriptive, they should be short: 99 100 func AfterFunc(d Duration, f func()) *Timer 101 102 func Escape(w io.Writer, s []byte) 103 104 Where the types are more ambiguous, the names may provide documentation: 105 106 func Unix(sec, nsec int64) Time 107 108 func HasPrefix(s, prefix []byte) bool 109 110 111 * Return values 112 113 Return values on exported functions should only be named for documentation purposes. 114 115 These are good examples of named return values: 116 117 func Copy(dst Writer, src Reader) (written int64, err error) 118 119 func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) 120 121 122 * Receivers 123 124 Receivers are a special kind of argument. 125 126 By convention, they are one or two characters that reflect the receiver type, 127 because they typically appear on almost every line: 128 129 func (b *Buffer) Read(p []byte) (n int, err error) 130 131 func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) 132 133 func (r Rectangle) Size() Point 134 135 Receiver names should be consistent across a type's methods. 136 (Don't use `r` in one method and `rdr` in another.) 137 138 139 * Exported package-level names 140 141 Exported names are qualified by their package names. 142 143 Remember this when naming exported variables, constants, functions, and types. 144 145 That's why we have `bytes.Buffer` and `strings.Reader`, 146 not `bytes.ByteBuffer` and `strings.StringReader`. 147 148 149 * Interface Types 150 151 Interfaces that specify just one method are usually just that function name with 'er' appended to it. 152 153 type Reader interface { 154 Read(p []byte) (n int, err error) 155 } 156 157 Sometimes the result isn't correct English, but we do it anyway: 158 159 type Execer interface { 160 Exec(query string, args []Value) (Result, error) 161 } 162 163 Sometimes we use English to make it nicer: 164 165 type ByteReader interface { 166 ReadByte() (c byte, err error) 167 } 168 169 When an interface includes multiple methods, choose a name that accurately describes its purpose (examples: `net.Conn`, `http.ResponseWriter`, `io.ReadWriter`). 170 171 172 * Errors 173 174 Error types should be of the form `FooError`: 175 176 type ExitError struct { 177 ... 178 } 179 180 Error values should be of the form `ErrFoo`: 181 182 var ErrFormat = errors.New("image: unknown format") 183 184 185 * Packages 186 187 Choose package names that lend meaning to the names they export. 188 189 Steer clear of `util`, `common`, and the like. 190 191 192 * Import paths 193 194 The last component of a package path should be the same as the package name. 195 196 "compress/gzip" // package gzip 197 198 Avoid stutter in repository and package paths: 199 200 "code.google.com/p/goauth2/oauth2" // bad; my fault 201 202 For libraries, it often works to put the package code in the repo root: 203 204 "github.com/golang/oauth2" // package oauth2 205 206 Also avoid upper case letters (not all file systems are case sensitive). 207 208 * The standard library 209 210 Many examples in this talk are from the standard library. 211 212 The standard library is a great place to find good Go code. 213 Look to it for inspiration. 214 215 But be warned: 216 217 When the standard library was written, we were still learning. 218 Most of it we got right, but we made some mistakes. 219 220 221 * Conclusion 222 223 Use short names. 224 225 Think about context. 226 227 Use your judgment. 228 229