blob: 9a858f339d2f2a77ac78663465ebe79609bf258e [file] [log] [blame] [view]
Andrew Gerrand5bc444d2014-12-10 11:35:11 +11001# Go Code Review Comments
2
3This page collects common comments made during reviews of Go code, so
4that a single detailed explanation can be referred to by shorthands.
5This is a laundry list of common mistakes, not a style guide.
6
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -07007You can view this as a supplement to https://golang.org/doc/effective_go.html.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +11008
9**Please discuss changes before editing this page**, even _minor_ ones. Many people have opinions and this is not the place for edit wars.
10
Jaana B. Dogan1583ba32017-01-30 11:52:43 -080011* [Gofmt](#gofmt)
nathany4d6a1bf2014-12-10 22:00:35 -080012* [Comment Sentences](#comment-sentences)
Jaana B. Doganb824d412017-01-30 09:25:17 -080013* [Contexts](#contexts)
Jaana B. Dogandcc731c2017-01-30 09:28:00 -080014* [Copying](#copying)
Jaana B. Doganf11f8f72017-01-30 10:05:50 -080015* [Crypto Rand](#cryptorand)
Earl J. Wagner7dda73c2015-01-05 11:43:49 -060016* [Declaring Empty Slices](#declaring-empty-slices)
nathany4d6a1bf2014-12-10 22:00:35 -080017* [Doc Comments](#doc-comments)
18* [Don't Panic](#dont-panic)
19* [Error Strings](#error-strings)
Jaana B. Doganb181e782017-01-30 09:36:22 -080020* [Examples](#examples)
Jaana B. Dogan8590e712017-01-30 09:38:59 -080021* [Goroutine Lifetimes](#goroutine-lifetimes)
nathany4d6a1bf2014-12-10 22:00:35 -080022* [Handle Errors](#handle-errors)
23* [Imports](#imports)
24* [Import Dot](#import-dot)
Jaana B. Doganad8c4452017-01-30 10:15:18 -080025* [In-Band Errors](#in-band-errors)
nathany4d6a1bf2014-12-10 22:00:35 -080026* [Indent Error Flow](#indent-error-flow)
27* [Initialisms](#initialisms)
Jaana B. Dogan88f0e012017-01-30 10:20:32 -080028* [Interfaces](#interfaces)
nathany4d6a1bf2014-12-10 22:00:35 -080029* [Line Length](#line-length)
30* [Mixed Caps](#mixed-caps)
31* [Named Result Parameters](#named-result-parameters)
32* [Naked Returns](#naked-returns)
33* [Package Comments](#package-comments)
34* [Package Names](#package-names)
35* [Pass Values](#pass-values)
36* [Receiver Names](#receiver-names)
37* [Receiver Type](#receiver-type)
38* [Useful Test Failures](#useful-test-failures)
39* [Variable Names](#variable-names)
40
Jaana B. Dogan1583ba32017-01-30 11:52:43 -080041## Gofmt
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110042
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -070043Run [gofmt](https://golang.org/cmd/gofmt/) on your code to automatically fix the majority of mechanical style issues. Almost all Go code in the wild uses `gofmt`. The rest of this document addresses non-mechanical style points.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110044
Andrew Gerrand2c6abb82016-02-09 08:25:13 +110045An alternative is to use [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports), a superset of `gofmt` which additionally adds (and removes) import lines as necessary.
46
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110047## Comment Sentences
48
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -070049See https://golang.org/doc/effective_go.html#commentary. Comments documenting declarations should be full sentences, even if that seems a little redundant. This approach makes them format well when extracted into godoc documentation. Comments should begin with the name of the thing being described and end in a period:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110050
nathany4d6a1bf2014-12-10 22:00:35 -080051```go
Martin Bertschler6db16492016-10-23 23:00:46 +020052// Request represents a request to run a command.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110053type Request struct { ...
54
55// Encode writes the JSON encoding of req to w.
56func Encode(w io.Writer, req *Request) { ...
57```
58
59and so on.
60
Jaana B. Doganb824d412017-01-30 09:25:17 -080061## Contexts
62
63Values of the context.Context type carry security credentials,
64tracing information, deadlines, and cancellation signals across API
65and process boundaries. Go programs pass Contexts explicitly along
66the entire function call chain from incoming RPCs and HTTP requests
67to outgoing requests.
68
69Most functions that use a Context should accept it as their first parameter:
70
71```
72func F(ctx context.Context, /* other arguments */) {}
73```
74
75A function that is never request-specific may use context.Background(),
76but err on the side of passing a Context even if you think you don't need
77to. The default case is to pass a Context; only use context.Background()
78directly if you have a good reason why the alternative is a mistake.
79
80Don't add a Context member to a struct type; instead add a ctx parameter
81to each method on that type that needs to pass it along. The one exception
82is for methods whose signature must match an interface in the standard library
83or in a third party library.
84
85Don't create custom Context types or use interfaces other than Context in
86function signatures.
87
88If you have application data to pass around, put it in a parameter,
89in the receiver, in globals, or, if it truly belongs there, in a Context value.
90
91Contexts are immutable, so it's fine to pass the same ctx to multiple
92calls that share the same deadline, cancellation signal, credentials,
93parent trace, etc.
94
Jaana B. Dogandcc731c2017-01-30 09:28:00 -080095## Copying
96
97To avoid unexpected aliasing, be careful when copying a struct from another package.
98For example, the bytes.Buffer type contains a `[]byte` slice and, as an optimization
99for small strings, a small byte array to which the slice may refer. If you copy a `Buffer`,
100the slice in the copy may alias the array in the original, causing subsequent method
101calls to have surprising effects.
102
103In general, do not copy a value of type `T` if its methods are associated with the
104pointer type, `*T`.
105
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600106## Declaring Empty Slices
107
Toby Allen771f1c72016-10-14 21:59:05 +0100108When declaring a slice, use
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600109```go
110var t []string
111```
Toby Allen771f1c72016-10-14 21:59:05 +0100112rather than
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600113```go
114t := []string{}
115```
116
Earl J. Wagnere3ee7b02015-01-11 15:20:33 -0600117The former avoids allocating memory if the slice is never appended to.
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600118
Jaana B. Doganf11f8f72017-01-30 10:05:50 -0800119## Crypto Rand
Jaana B. Dogan9b339332017-01-30 09:32:22 -0800120
121Do not use package `math/rand` to generate keys, even throwaway ones.
122Unseeded, the generator is completely predictable. Seeded with `time.Nanoseconds()`,
123there are just a few bits of entropy. Instead, use `crypto/rand`'s Reader,
124and if you need text, print to hexadecimal or base64:
125
126``` go
127import (
128 "crypto/rand"
129 // "encoding/base64"
130 // "encoding/hex"
131 "fmt"
132)
133
134func Key() string {
135 buf := make([]byte, 16)
136 _, err := rand.Read(buf)
137 if err != nil {
138 panic(err) // out of randomness, should never happen
139 }
140 return fmt.Sprintf("%x", buf)
141 // or hex.EncodeToString(buf)
142 // or base64.StdEncoding.EncodeToString(buf)
143}
144```
145
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100146## Doc Comments
147
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700148All top-level, exported names should have doc comments, as should non-trivial unexported type or function declarations. See https://golang.org/doc/effective_go.html#commentary for more information about commentary conventions.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100149
150## Don't Panic
151
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700152See https://golang.org/doc/effective_go.html#errors. Don't use panic for normal error handling. Use error and multiple return values.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100153
154## Error Strings
155
Steve Carrupt6a3e3082016-11-24 09:49:46 +0900156Error strings should not be capitalized (unless beginning with proper nouns or acronyms) or end with punctuation, since they are usually printed following other context. That is, use `fmt.Errorf("something bad")` not `fmt.Errorf("Something bad")`, so that `log.Printf("Reading %s: %v", filename, err)` formats without a spurious capital letter mid-message. This does not apply to logging, which is implicitly line-oriented and not combined inside other messages.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100157
Jaana B. Doganb181e782017-01-30 09:36:22 -0800158## Examples
159
160When adding a new package, include examples of intended usage: a runnable Example,
161or a simple test demonstrating a complete call sequence.
162
163Read more about [testable Example() functions](https://blog.golang.org/examples).
164
Jaana B. Dogan8590e712017-01-30 09:38:59 -0800165## Goroutine Lifetimes
166
167When you spawn goroutines, make it clear when - or whether - they exit.
168
169Goroutines can leak by blocking on channel sends or receives: the garbage collector
170will not terminate a goroutine even if the channels it is blocked on are unreachable.
171
172Even when goroutines do not leak, leaving them in-flight when they are no longer
173needed can cause other subtle and hard-to-diagnose problems. Sends on closed channels
174panic. Modifying still-in-use inputs "after the result isn't needed" can still lead
175to data races. And leaving goroutines in-flight for arbitrarily long can lead to
176unpredictable memory usage.
177
178Try to keep concurrent code simple enough that goroutine lifetimes are obvious.
179If that just isn't feasible, document when and why the goroutines exit.
Jaana B. Doganb181e782017-01-30 09:36:22 -0800180
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100181## Handle Errors
182
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700183See https://golang.org/doc/effective_go.html#errors. Do not discard errors using `_` variables. If a function returns an error, check it to make sure the function succeeded. Handle the error, return it, or, in truly exceptional situations, panic.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100184
185## Imports
186
Jaana B. Dogan860d7842017-01-30 10:08:02 -0800187Avoid renaming imports except to avoid a name collision; good package names
188should not require renaming. In the event of collision, prefer to rename the most
189local or project-specific import.
190
191
192Imports are organized in groups, with blank lines between them.
193The standard library packages are always in the first group.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100194
nathany4d6a1bf2014-12-10 22:00:35 -0800195```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100196package main
197
198import (
Dave Day0d6986a2014-12-10 15:02:18 +1100199 "fmt"
200 "hash/adler32"
201 "os"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100202
Dave Day0d6986a2014-12-10 15:02:18 +1100203 "appengine/foo"
204 "appengine/user"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100205
Dave Day0d6986a2014-12-10 15:02:18 +1100206 "code.google.com/p/x/y"
207 "github.com/foo/bar"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100208)
209```
210
nathany4d6a1bf2014-12-10 22:00:35 -0800211<a href="https://godoc.org/golang.org/x/tools/cmd/goimports">goimports</a> will do this for you.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100212
213## Import Dot
214
215The import . form can be useful in tests that, due to circular dependencies, cannot be made part of the package being tested:
216
nathany4d6a1bf2014-12-10 22:00:35 -0800217```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100218package foo_test
219
220import (
Dave Day0d6986a2014-12-10 15:02:18 +1100221 "bar/testutil" // also imports "foo"
222 . "foo"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100223)
224```
225
226In this case, the test file cannot be in package foo because it uses bar/testutil, which imports foo. So we use the 'import .' form to let the file pretend to be part of package foo even though it is not. Except for this one case, do not use import . in your programs. It makes the programs much harder to read because it is unclear whether a name like Quux is a top-level identifier in the current package or in an imported package.
227
Jaana B. Doganad8c4452017-01-30 10:15:18 -0800228## In-Band Errors
229
230In C and similar languages, it's common for functions to return values like -1
231or null to signal errors or missing results:
232
233```go
234// Lookup returns the value for key or "" if there is no mapping for key.
235func Lookup(key string) string
236
237// Failing to check a for an in-band error value can lead to bugs:
238Parse(Lookup(key)) // returns "parse failure for value" instead of "no value for key"
239```
240
241Go's support for multiple return values provides a better solution.
242Instead requiring clients to check for an in-band error value, a function should return
243an additional value to indicate whether its other return values are valid. This return
244value may be an error, or a boolean when no explanation is needed.
245It should be the final return value.
246
247``` go
248// Lookup returns the value for key or ok=false if there is no mapping for key.
249func Lookup(key string) (value string, ok bool)
250```
251
252This prevents the caller from using the result incorrectly:
253
254``` go
255Parse(Lookup(key)) // compile-time error
256```
257
258And encourages more robust and readable code:
259
260``` go
261value, ok := Lookup(key)
262if !ok {
263 return fmt.Errorf("no value for %q", key)
264}
265return Parse(value)
266```
267
268This rule applies to exported functions but is also useful
269for unexported functions.
270
271Return values like nil, "", 0, and -1 are fine when they are
272valid results for a function, that is, when the caller need not
273handle them differently from other values.
274
275Some standard library functions, like those in package "strings",
276return in-band error values. This greatly simplifies string-manipulation
277code at the cost of requiring more diligence from the programmer.
278In general, Google Go code should return additional values for errors.
279
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100280## Indent Error Flow
281
nathany4d6a1bf2014-12-10 22:00:35 -0800282Try to keep the normal code path at a minimal indentation, and indent the error handling, dealing with it first. This improves the readability of the code by permitting visually scanning the normal path quickly. For instance, don't write:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100283
nathany4d6a1bf2014-12-10 22:00:35 -0800284```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100285if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100286 // error handling
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100287} else {
Dave Day0d6986a2014-12-10 15:02:18 +1100288 // normal code
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100289}
290```
291
nathany4d6a1bf2014-12-10 22:00:35 -0800292Instead, write:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100293
nathany4d6a1bf2014-12-10 22:00:35 -0800294```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100295if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100296 // error handling
297 return // or continue, etc.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100298}
299// normal code
300```
301
nathany4d6a1bf2014-12-10 22:00:35 -0800302If the if statement has an initialization statement that, such as:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100303
nathany4d6a1bf2014-12-10 22:00:35 -0800304```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100305if x, err := f(); err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100306 // error handling
307 return
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100308} else {
Dave Day0d6986a2014-12-10 15:02:18 +1100309 // use x
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100310}
311```
312
313then this may require moving the short variable declaration to its own line:
314
nathany4d6a1bf2014-12-10 22:00:35 -0800315```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100316x, err := f()
317if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100318 // error handling
319 return
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100320}
321// use x
322```
323
324## Initialisms
325
326Words in names that are initialisms or acronyms (e.g. "URL" or "NATO") have a consistent case. For example, "URL" should appear as "URL" or "url" (as in "urlPony", or "URLPony"), never as "Url". Here's an example: ServeHTTP not ServeHttp.
327
328This rule also applies to "ID" when it is short for "identifier," so write "appID" instead of "appId".
329
330Code generated by the protocol buffer compiler is exempt from this rule. Human-written code is held to a higher standard than machine-written code.
331
Jaana B. Dogan88f0e012017-01-30 10:20:32 -0800332## Interfaces
333
334Go interfaces generally belong in the package that uses values of the
335interface type, not the package that implements those values. The
336implementing package should return concrete (usually pointer or struct)
337types: that way, new methods can be added to implementations without
338requiring extensive refactoring.
339
340Do not define interfaces on the implementor side of an API "for mocking";
341instead, design the API so that it can be tested using the public API of
342the real implementation.
343
344Do not define interfaces before they are used: without a realistic example
345of usage, it is too difficult to see whether an interface is even necessary,
346let alone what methods it ought to contain.
347
348``` go
349package consumer // consumer.go
350
351type Thinger interface { Thing() bool }
352
353func Foo(t Thinger) string { … }
354```
355
356``` go
357package consumer // consumer_test.go
358
359type fakeThinger struct{ … }
360func (t fakeThinger) Thing() bool { … }
361…
362if Foo(fakeThinger{…}) == "x" { … }
363```
364
365``` go
366// DO NOT DO IT!!!
367package producer
368
369type Thinger interface { Thing() bool }
370
371type defaultThinger struct{ … }
372func (t defaultThinger) Thing() bool { … }
373
374func NewThinger() Thinger { return defaultThinger{ … } }
375```
376
377Instead return a concrete type and let the consumer mock the producer implementation.
378``` go
379package producer
380
381type Thinger struct{ … }
382func (t Thinger) Thing() bool { … }
383
384func NewThinger() Thinger { return Thinger{ … } }
385```
386
387
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100388## Line Length
389
Jaana B. Dogan28407542017-01-30 10:55:16 -0800390There is no rigid line length limit in Go code, but avoid uncomfortably long lines.
391Similarly, don't add line breaks to keep lines short when they are more readable long--for example,
392if they are repetitive.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100393
Jaana B. Dogan28407542017-01-30 10:55:16 -0800394Most of the time when people wrap lines "unnaturally" (in the middle of function calls or
395function declarations, more or less, say, though some exceptions are around), the wrapping would be
396unnecessary if they had a reasonable number of parameters and reasonably short variable names.
397Long lines seem to go with long names, and getting rid of the long names helps a lot.
398
399In other words, break lines because of the semantics of what you're writing (as a general rule)
400and not because of the length of the line. If you find that this produces lines that are too long,
401then change the names or the semantics and you'll probably get a good result.
402
403This is, actually, exactly the same advice about how long a function should be. There's no rule
404"never have a function more than N lines long", but there is definitely such a thing as too long
405of a function, and of too stuttery tiny functions, and the solution is to change where the function
406boundaries are, not to start counting lines.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100407
408## Mixed Caps
409
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700410See https://golang.org/doc/effective_go.html#mixed-caps. This applies even when it breaks conventions in other languages. For example an unexported constant is `maxLength` not `MaxLength` or `MAX_LENGTH`.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100411
412## Named Result Parameters
413
414Consider what it will look like in godoc. Named result parameters like:
415
nathany4d6a1bf2014-12-10 22:00:35 -0800416```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100417func (n *Node) Parent1() (node *Node)
418func (n *Node) Parent2() (node *Node, err error)
419```
nathany4d6a1bf2014-12-10 22:00:35 -0800420
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100421will stutter in godoc; better to use:
nathany4d6a1bf2014-12-10 22:00:35 -0800422
423```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100424func (n *Node) Parent1() *Node
425func (n *Node) Parent2() (*Node, error)
426```
427
Jaana B. Dogan0df7fa52017-01-30 11:51:05 -0800428On the other hand, if a function returns two or three parameters of the same type,
429or if the meaning of a result isn't clear from context, adding names may be useful
430in some contexts. Don't name result parameters just to avoid declaring a var inside
431the function; that trades off a minor implementation brevity at the cost of
432unnecessary API verbosity.
433
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100434
435```go
Dave Day0d6986a2014-12-10 15:02:18 +1100436func (f *Foo) Location() (float64, float64, error)
437```
nathany4d6a1bf2014-12-10 22:00:35 -0800438
439is less clear than:
440
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100441```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100442// Location returns f's latitude and longitude.
443// Negative values mean south and west, respectively.
Dave Day0d6986a2014-12-10 15:02:18 +1100444func (f *Foo) Location() (lat, long float64, err error)
445```
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100446
Jaana B. Dogan0df7fa52017-01-30 11:51:05 -0800447Naked returns are okay if the function is a handful of lines. Once it's a medium
448sized function, be explicit with your return values. Corollary: it's not worth it
449to name result parameters just because it enables you to use naked returns.
450Clarity of docs is always more important than saving a line or two in your function.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100451
Jaana B. Dogan0df7fa52017-01-30 11:51:05 -0800452Finally, in some cases you need to name a result parameter in order to change
453it in a deferred closure. That is always OK.
454
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100455
456## Naked Returns
457
nathany812cb132014-12-10 22:35:33 -0800458See [Named Result Parameters](#named-result-parameters).
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100459
460## Package Comments
461
462Package comments, like all comments to be presented by godoc, must appear adjacent to the package clause, with no blank line.
463
nathany4d6a1bf2014-12-10 22:00:35 -0800464```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100465// Package math provides basic constants and mathematical functions.
466package math
467```
468
nathany4d6a1bf2014-12-10 22:00:35 -0800469```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100470/*
471Package template implements data-driven templates for generating textual
472output such as HTML.
473....
474*/
475package template
476```
477
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800478Other styles of comment are fine after the binary name (and it may be capitalized if it comes first).
479For example,
480
Jaana B. Dogan4ac42e32017-01-30 11:04:39 -0800481``` go
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800482// Binary seedgen ...
483// Command seedgen ...
484// Program seedgen ...
485// The seedgen command ...
486// The seedgen program ...
487// Seedgen ..
488```
489
490These are examples, and sensible variants of these are acceptable.
491
492Note that starting the sentence with a lower-case word is not among the
493acceptable options for package comments, as these are publicly-visible and
494should be written in proper English, including capitalizing the first word
495of the sentence. When the binary name is the first word, capitalizing it is
496required even though it does not strictly match the spelling of the
497command-line invocation.
498
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700499See https://golang.org/doc/effective_go.html#commentary for more information about commentary conventions.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100500
501## Package Names
502
Jaana B. Dogan17559282017-01-30 11:55:39 -0800503All references to names in your package will be done using the package name,
504so you can omit that name from the identifiers. For example, if you are in package chubby,
505you don't need type ChubbyFile, which clients will write as `chubby.ChubbyFile`.
506Instead, name the type `File`, which clients will write as `chubby.File`.
507Avoid meaningless package names like util, common, misc, api, types, and interfaces. See http://golang.org/doc/effective_go.html#package-names and
508http://blog.golang.org/package-names for more.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100509
510## Pass Values
511
Dave Day0d6986a2014-12-10 15:02:18 +1100512Don't pass pointers as function arguments just to save a few bytes. If a function refers to its argument `x` only as `*x` throughout, then the argument shouldn't be a pointer. Common instances of this include passing a pointer to a string (`*string`) or a pointer to an interface value (`*io.Reader`). In both cases the value itself is a fixed size and can be passed directly. This advice does not apply to large structs, or even small structs that might grow.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100513
514## Receiver Names
515
Christopher Dunn4cb9dac2016-07-03 12:24:45 -0700516The name of a method's receiver should be a reflection of its identity; often a one or two letter abbreviation of its type suffices (such as "c" or "cl" for "Client"). Don't use generic names such as "me", "this" or "self", identifiers typical of object-oriented languages that place more emphasis on methods as opposed to functions. The name need not be as descriptive as that of a method argument, as its role is obvious and serves no documentary purpose. It can be very short as it will appear on almost every line of every method of the type; familiarity admits brevity. Be consistent, too: if you call the receiver "c" in one method, don't call it "cl" in another.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100517
518## Receiver Type
519
Kevin Gillette68ab16c2016-02-19 10:33:35 -0700520Choosing whether to use a value or pointer receiver on methods can be difficult, especially to new Go programmers. If in doubt, use a pointer, but there are times when a value receiver makes sense, usually for reasons of efficiency, such as for small unchanging structs or values of basic type. Some useful guidelines:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100521
Jaana B. Dogan7ca7f1f2017-01-30 13:59:18 -0800522 * If the receiver is a map, func or chan, don't use a pointer to them. If the receiver is a slice and the method doesn't reslice or reallocate the slice, don't use a pointer to it.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100523 * If the method needs to mutate the receiver, the receiver must be a pointer.
524 * If the receiver is a struct that contains a sync.Mutex or similar synchronizing field, the receiver must be a pointer to avoid copying.
525 * If the receiver is a large struct or array, a pointer receiver is more efficient. How large is large? Assume it's equivalent to passing all its elements as arguments to the method. If that feels too large, it's also too large for the receiver.
526 * Can function or methods, either concurrently or when called from this method, be mutating the receiver? A value type creates a copy of the receiver when the method is invoked, so outside updates will not be applied to this receiver. If changes must be visible in the original receiver, the receiver must be a pointer.
527 * If the receiver is a struct, array or slice and any of its elements is a pointer to something that might be mutating, prefer a pointer receiver, as it will make the intention more clear to the reader.
528 * If the receiver is a small array or struct that is naturally a value type (for instance, something like the time.Time type), with no mutable fields and no pointers, or is just a simple basic type such as int or string, a value receiver makes sense. A value receiver can reduce the amount of garbage that can be generated; if a value is passed to a value method, an on-stack copy can be used instead of allocating on the heap. (The compiler tries to be smart about avoiding this allocation, but it can't always succeed.) Don't choose a value receiver type for this reason without profiling first.
529 * Finally, when in doubt, use a pointer receiver.
530
531## Useful Test Failures
532
533Tests should fail with helpful messages saying what was wrong, with what inputs, what was actually got, and what was expected. It may be tempting to write a bunch of assertFoo helpers, but be sure your helpers produce useful error messages. Assume that the person debugging your failing test is not you, and is not your team. A typical Go test fails like:
534
nathany4d6a1bf2014-12-10 22:00:35 -0800535```go
Dave Day0d6986a2014-12-10 15:02:18 +1100536if got != tt.want {
537 t.Errorf("Foo(%q) = %d; want %d", tt.in, got, tt.want) // or Fatalf, if test can't test anything more past this point
538}
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100539```
540
541Note that the order here is actual != expected, and the message uses that order too. Some test frameworks encourage writing these backwards: 0 != x, "expected 0, got x", and so on. Go does not.
542
nathany4d6a1bf2014-12-10 22:00:35 -0800543If that seems like a lot of typing, you may want to write a [[table-driven test|TableDrivenTests]].
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100544
545Another common technique to disambiguate failing tests when using a test helper with different input is to wrap each caller with a different TestFoo function, so the test fails with that name:
546
nathany4d6a1bf2014-12-10 22:00:35 -0800547```go
Dave Day0d6986a2014-12-10 15:02:18 +1100548func TestSingleValue(t *testing.T) { testHelper(t, []int{80}) }
549func TestNoValues(t *testing.T) { testHelper(t, []int{}) }
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100550```
551
552In any case, the onus is on you to fail with a helpful message to whoever's debugging your code in the future.
553
554## Variable Names
555
556Variable names in Go should be short rather than long. This is especially true for local variables with limited scope. Prefer c to lineCount. Prefer i to sliceIndex.
557
Dave Day0d6986a2014-12-10 15:02:18 +1100558The basic rule: the further from its declaration that a name is used, the more descriptive the name must be. For a method receiver, one or two letters is sufficient. Common variables such as loop indices and readers can be a single letter (`i`, `r`). More unusual things and global variables need more descriptive names.