blob: 207fbb5e2775a55001d271285315cdb456fb2005 [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
Andrew Gerrande6f82132016-02-09 08:26:28 +110011* [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)
28* [Line Length](#line-length)
29* [Mixed Caps](#mixed-caps)
30* [Named Result Parameters](#named-result-parameters)
31* [Naked Returns](#naked-returns)
32* [Package Comments](#package-comments)
33* [Package Names](#package-names)
34* [Pass Values](#pass-values)
35* [Receiver Names](#receiver-names)
36* [Receiver Type](#receiver-type)
37* [Useful Test Failures](#useful-test-failures)
38* [Variable Names](#variable-names)
39
Andrew Gerrande6f82132016-02-09 08:26:28 +110040## gofmt
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110041
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -070042Run [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 +110043
Andrew Gerrand2c6abb82016-02-09 08:25:13 +110044An 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.
45
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110046## Comment Sentences
47
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -070048See 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 +110049
nathany4d6a1bf2014-12-10 22:00:35 -080050```go
Martin Bertschler6db16492016-10-23 23:00:46 +020051// Request represents a request to run a command.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110052type Request struct { ...
53
54// Encode writes the JSON encoding of req to w.
55func Encode(w io.Writer, req *Request) { ...
56```
57
58and so on.
59
Jaana B. Doganb824d412017-01-30 09:25:17 -080060## Contexts
61
62Values of the context.Context type carry security credentials,
63tracing information, deadlines, and cancellation signals across API
64and process boundaries. Go programs pass Contexts explicitly along
65the entire function call chain from incoming RPCs and HTTP requests
66to outgoing requests.
67
68Most functions that use a Context should accept it as their first parameter:
69
70```
71func F(ctx context.Context, /* other arguments */) {}
72```
73
74A function that is never request-specific may use context.Background(),
75but err on the side of passing a Context even if you think you don't need
76to. The default case is to pass a Context; only use context.Background()
77directly if you have a good reason why the alternative is a mistake.
78
79Don't add a Context member to a struct type; instead add a ctx parameter
80to each method on that type that needs to pass it along. The one exception
81is for methods whose signature must match an interface in the standard library
82or in a third party library.
83
84Don't create custom Context types or use interfaces other than Context in
85function signatures.
86
87If you have application data to pass around, put it in a parameter,
88in the receiver, in globals, or, if it truly belongs there, in a Context value.
89
90Contexts are immutable, so it's fine to pass the same ctx to multiple
91calls that share the same deadline, cancellation signal, credentials,
92parent trace, etc.
93
Jaana B. Dogandcc731c2017-01-30 09:28:00 -080094## Copying
95
96To avoid unexpected aliasing, be careful when copying a struct from another package.
97For example, the bytes.Buffer type contains a `[]byte` slice and, as an optimization
98for small strings, a small byte array to which the slice may refer. If you copy a `Buffer`,
99the slice in the copy may alias the array in the original, causing subsequent method
100calls to have surprising effects.
101
102In general, do not copy a value of type `T` if its methods are associated with the
103pointer type, `*T`.
104
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600105## Declaring Empty Slices
106
Toby Allen771f1c72016-10-14 21:59:05 +0100107When declaring a slice, use
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600108```go
109var t []string
110```
Toby Allen771f1c72016-10-14 21:59:05 +0100111rather than
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600112```go
113t := []string{}
114```
115
Earl J. Wagnere3ee7b02015-01-11 15:20:33 -0600116The former avoids allocating memory if the slice is never appended to.
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600117
Jaana B. Doganf11f8f72017-01-30 10:05:50 -0800118## Crypto Rand
Jaana B. Dogan9b339332017-01-30 09:32:22 -0800119
120Do not use package `math/rand` to generate keys, even throwaway ones.
121Unseeded, the generator is completely predictable. Seeded with `time.Nanoseconds()`,
122there are just a few bits of entropy. Instead, use `crypto/rand`'s Reader,
123and if you need text, print to hexadecimal or base64:
124
125``` go
126import (
127 "crypto/rand"
128 // "encoding/base64"
129 // "encoding/hex"
130 "fmt"
131)
132
133func Key() string {
134 buf := make([]byte, 16)
135 _, err := rand.Read(buf)
136 if err != nil {
137 panic(err) // out of randomness, should never happen
138 }
139 return fmt.Sprintf("%x", buf)
140 // or hex.EncodeToString(buf)
141 // or base64.StdEncoding.EncodeToString(buf)
142}
143```
144
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100145## Doc Comments
146
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700147All 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 +1100148
149## Don't Panic
150
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700151See 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 +1100152
153## Error Strings
154
Steve Carrupt6a3e3082016-11-24 09:49:46 +0900155Error 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 +1100156
Jaana B. Doganb181e782017-01-30 09:36:22 -0800157## Examples
158
159When adding a new package, include examples of intended usage: a runnable Example,
160or a simple test demonstrating a complete call sequence.
161
162Read more about [testable Example() functions](https://blog.golang.org/examples).
163
Jaana B. Dogan8590e712017-01-30 09:38:59 -0800164## Goroutine Lifetimes
165
166When you spawn goroutines, make it clear when - or whether - they exit.
167
168Goroutines can leak by blocking on channel sends or receives: the garbage collector
169will not terminate a goroutine even if the channels it is blocked on are unreachable.
170
171Even when goroutines do not leak, leaving them in-flight when they are no longer
172needed can cause other subtle and hard-to-diagnose problems. Sends on closed channels
173panic. Modifying still-in-use inputs "after the result isn't needed" can still lead
174to data races. And leaving goroutines in-flight for arbitrarily long can lead to
175unpredictable memory usage.
176
177Try to keep concurrent code simple enough that goroutine lifetimes are obvious.
178If that just isn't feasible, document when and why the goroutines exit.
Jaana B. Doganb181e782017-01-30 09:36:22 -0800179
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100180## Handle Errors
181
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700182See 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 +1100183
184## Imports
185
Jaana B. Dogan860d7842017-01-30 10:08:02 -0800186Avoid renaming imports except to avoid a name collision; good package names
187should not require renaming. In the event of collision, prefer to rename the most
188local or project-specific import.
189
190
191Imports are organized in groups, with blank lines between them.
192The standard library packages are always in the first group.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100193
nathany4d6a1bf2014-12-10 22:00:35 -0800194```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100195package main
196
197import (
Dave Day0d6986a2014-12-10 15:02:18 +1100198 "fmt"
199 "hash/adler32"
200 "os"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100201
Dave Day0d6986a2014-12-10 15:02:18 +1100202 "appengine/foo"
203 "appengine/user"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100204
Dave Day0d6986a2014-12-10 15:02:18 +1100205 "code.google.com/p/x/y"
206 "github.com/foo/bar"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100207)
208```
209
nathany4d6a1bf2014-12-10 22:00:35 -0800210<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 +1100211
212## Import Dot
213
214The import . form can be useful in tests that, due to circular dependencies, cannot be made part of the package being tested:
215
nathany4d6a1bf2014-12-10 22:00:35 -0800216```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100217package foo_test
218
219import (
Dave Day0d6986a2014-12-10 15:02:18 +1100220 "bar/testutil" // also imports "foo"
221 . "foo"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100222)
223```
224
225In 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.
226
Jaana B. Doganad8c4452017-01-30 10:15:18 -0800227## In-Band Errors
228
229In C and similar languages, it's common for functions to return values like -1
230or null to signal errors or missing results:
231
232```go
233// Lookup returns the value for key or "" if there is no mapping for key.
234func Lookup(key string) string
235
236// Failing to check a for an in-band error value can lead to bugs:
237Parse(Lookup(key)) // returns "parse failure for value" instead of "no value for key"
238```
239
240Go's support for multiple return values provides a better solution.
241Instead requiring clients to check for an in-band error value, a function should return
242an additional value to indicate whether its other return values are valid. This return
243value may be an error, or a boolean when no explanation is needed.
244It should be the final return value.
245
246``` go
247// Lookup returns the value for key or ok=false if there is no mapping for key.
248func Lookup(key string) (value string, ok bool)
249```
250
251This prevents the caller from using the result incorrectly:
252
253``` go
254Parse(Lookup(key)) // compile-time error
255```
256
257And encourages more robust and readable code:
258
259``` go
260value, ok := Lookup(key)
261if !ok {
262 return fmt.Errorf("no value for %q", key)
263}
264return Parse(value)
265```
266
267This rule applies to exported functions but is also useful
268for unexported functions.
269
270Return values like nil, "", 0, and -1 are fine when they are
271valid results for a function, that is, when the caller need not
272handle them differently from other values.
273
274Some standard library functions, like those in package "strings",
275return in-band error values. This greatly simplifies string-manipulation
276code at the cost of requiring more diligence from the programmer.
277In general, Google Go code should return additional values for errors.
278
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100279## Indent Error Flow
280
nathany4d6a1bf2014-12-10 22:00:35 -0800281Try 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 +1100282
nathany4d6a1bf2014-12-10 22:00:35 -0800283```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100284if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100285 // error handling
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100286} else {
Dave Day0d6986a2014-12-10 15:02:18 +1100287 // normal code
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100288}
289```
290
nathany4d6a1bf2014-12-10 22:00:35 -0800291Instead, write:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100292
nathany4d6a1bf2014-12-10 22:00:35 -0800293```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100294if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100295 // error handling
296 return // or continue, etc.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100297}
298// normal code
299```
300
nathany4d6a1bf2014-12-10 22:00:35 -0800301If the if statement has an initialization statement that, such as:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100302
nathany4d6a1bf2014-12-10 22:00:35 -0800303```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100304if x, err := f(); err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100305 // error handling
306 return
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100307} else {
Dave Day0d6986a2014-12-10 15:02:18 +1100308 // use x
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100309}
310```
311
312then this may require moving the short variable declaration to its own line:
313
nathany4d6a1bf2014-12-10 22:00:35 -0800314```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100315x, err := f()
316if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100317 // error handling
318 return
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100319}
320// use x
321```
322
323## Initialisms
324
325Words 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.
326
327This rule also applies to "ID" when it is short for "identifier," so write "appID" instead of "appId".
328
329Code generated by the protocol buffer compiler is exempt from this rule. Human-written code is held to a higher standard than machine-written code.
330
331## Line Length
332
333There is no rigid line length limit in Go code, but avoid uncomfortably long lines. Similarly, don't add line breaks to keep lines short when they are more readable long--for example, if they are repetitive.
334
335Comments are typically wrapped before no more than 80 characters, not because it's a rule, but because it's more readable when viewing in an editor that might be sized to show hundreds of columns wide. Humans are better at following narrow text (e.g. columns in a newspaper) than giant walls of wide text, as a wide editor might show. Regardless, godoc should render it nicely either way.
336
337## Mixed Caps
338
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700339See 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 +1100340
341## Named Result Parameters
342
343Consider what it will look like in godoc. Named result parameters like:
344
nathany4d6a1bf2014-12-10 22:00:35 -0800345```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100346func (n *Node) Parent1() (node *Node)
347func (n *Node) Parent2() (node *Node, err error)
348```
nathany4d6a1bf2014-12-10 22:00:35 -0800349
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100350will stutter in godoc; better to use:
nathany4d6a1bf2014-12-10 22:00:35 -0800351
352```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100353func (n *Node) Parent1() *Node
354func (n *Node) Parent2() (*Node, error)
355```
356
357On the other hand, if a function returns two or three parameters of the same type, or if the meaning of a result isn't clear from context, adding names may be useful. For example:
358
359```go
Dave Day0d6986a2014-12-10 15:02:18 +1100360func (f *Foo) Location() (float64, float64, error)
361```
nathany4d6a1bf2014-12-10 22:00:35 -0800362
363is less clear than:
364
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100365```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100366// Location returns f's latitude and longitude.
367// Negative values mean south and west, respectively.
Dave Day0d6986a2014-12-10 15:02:18 +1100368func (f *Foo) Location() (lat, long float64, err error)
369```
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100370
371Naked returns are okay if the function is a handful of lines. Once it's a medium-sized function, be explicit with your return values. Corollary: it's not worth it to name result parameters just because it enables you to use naked returns. Clarity of docs is always more important than saving a line or two in your function.
372
373Finally, in some cases you need to name a result parameter in order to change it in a deferred closure. That is always okay.
374
375## Naked Returns
376
nathany812cb132014-12-10 22:35:33 -0800377See [Named Result Parameters](#named-result-parameters).
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100378
379## Package Comments
380
381Package comments, like all comments to be presented by godoc, must appear adjacent to the package clause, with no blank line.
382
nathany4d6a1bf2014-12-10 22:00:35 -0800383```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100384// Package math provides basic constants and mathematical functions.
385package math
386```
387
nathany4d6a1bf2014-12-10 22:00:35 -0800388```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100389/*
390Package template implements data-driven templates for generating textual
391output such as HTML.
392....
393*/
394package template
395```
396
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700397See https://golang.org/doc/effective_go.html#commentary for more information about commentary conventions.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100398
399## Package Names
400
Terry Liu0e2fe192016-10-21 22:20:03 -0700401All references to names in your package will be done using the package name, so you can omit that name from the identifiers. For example, if you are in package chubby, you don't need to type ChubbyFile, which clients will write as chubby.ChubbyFile. Instead, name the type File, which clients will write as chubby.File. See https://golang.org/doc/effective_go.html#package-names for more.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100402
403## Pass Values
404
Dave Day0d6986a2014-12-10 15:02:18 +1100405Don'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 +1100406
407## Receiver Names
408
Christopher Dunn4cb9dac2016-07-03 12:24:45 -0700409The 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 +1100410
411## Receiver Type
412
Kevin Gillette68ab16c2016-02-19 10:33:35 -0700413Choosing 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 +1100414
415 * If the receiver is a map, func or chan, don't use a pointer to it.
416 * If the receiver is a slice and the method doesn't reslice or reallocate the slice, don't use a pointer to it.
417 * If the method needs to mutate the receiver, the receiver must be a pointer.
418 * If the receiver is a struct that contains a sync.Mutex or similar synchronizing field, the receiver must be a pointer to avoid copying.
419 * 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.
420 * 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.
421 * 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.
422 * 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.
423 * Finally, when in doubt, use a pointer receiver.
424
425## Useful Test Failures
426
427Tests 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:
428
nathany4d6a1bf2014-12-10 22:00:35 -0800429```go
Dave Day0d6986a2014-12-10 15:02:18 +1100430if got != tt.want {
431 t.Errorf("Foo(%q) = %d; want %d", tt.in, got, tt.want) // or Fatalf, if test can't test anything more past this point
432}
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100433```
434
435Note 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.
436
nathany4d6a1bf2014-12-10 22:00:35 -0800437If that seems like a lot of typing, you may want to write a [[table-driven test|TableDrivenTests]].
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100438
439Another 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:
440
nathany4d6a1bf2014-12-10 22:00:35 -0800441```go
Dave Day0d6986a2014-12-10 15:02:18 +1100442func TestSingleValue(t *testing.T) { testHelper(t, []int{80}) }
443func TestNoValues(t *testing.T) { testHelper(t, []int{}) }
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100444```
445
446In any case, the onus is on you to fail with a helpful message to whoever's debugging your code in the future.
447
448## Variable Names
449
450Variable 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.
451
Dave Day0d6986a2014-12-10 15:02:18 +1100452The 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.