blob: b998e9fa9f9a391040eaa44a21aa8bd34d12b572 [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.
Ian Lance Taylor5a40ba32018-07-26 16:56:05 -07005This is a laundry list of common mistakes, not a comprehensive style guide.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +11006
Tomoya Ishizaki2456bc22018-03-03 10:00:37 +09007You can view this as a supplement to [Effective Go](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)
Kenny Grantc9f7de72017-01-31 13:46:31 +000015* [Crypto Rand](#crypto-rand)
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)
Jaana B. Dogan220c5342017-01-30 14:01:00 -080038* [Synchronous Functions](#synchronous-functions)
nathany4d6a1bf2014-12-10 22:00:35 -080039* [Useful Test Failures](#useful-test-failures)
40* [Variable Names](#variable-names)
41
Jaana B. Dogan1583ba32017-01-30 11:52:43 -080042## Gofmt
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110043
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -070044Run [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 +110045
Andrew Gerrand2c6abb82016-02-09 08:25:13 +110046An 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.
47
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110048## Comment Sentences
49
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -070050See 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 +110051
nathany4d6a1bf2014-12-10 22:00:35 -080052```go
Martin Bertschler6db16492016-10-23 23:00:46 +020053// Request represents a request to run a command.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110054type Request struct { ...
55
56// Encode writes the JSON encoding of req to w.
57func Encode(w io.Writer, req *Request) { ...
58```
59
Victor van Poppelendbdd5b02018-05-08 15:42:04 -070060and so on. Note that there are other symbols except a period that can be a valid end of sentence (at least !, ?). Apart from that there are many tools that use comments to mark types and methods (like easyjson:json and golint's MATCH). It makes this rule hard to formalize.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110061
Jaana B. Doganb824d412017-01-30 09:25:17 -080062## Contexts
63
64Values of the context.Context type carry security credentials,
65tracing information, deadlines, and cancellation signals across API
66and process boundaries. Go programs pass Contexts explicitly along
67the entire function call chain from incoming RPCs and HTTP requests
68to outgoing requests.
69
70Most functions that use a Context should accept it as their first parameter:
71
72```
73func F(ctx context.Context, /* other arguments */) {}
74```
75
76A function that is never request-specific may use context.Background(),
77but err on the side of passing a Context even if you think you don't need
78to. The default case is to pass a Context; only use context.Background()
79directly if you have a good reason why the alternative is a mistake.
80
81Don't add a Context member to a struct type; instead add a ctx parameter
82to each method on that type that needs to pass it along. The one exception
83is for methods whose signature must match an interface in the standard library
84or in a third party library.
85
86Don't create custom Context types or use interfaces other than Context in
87function signatures.
88
89If you have application data to pass around, put it in a parameter,
90in the receiver, in globals, or, if it truly belongs there, in a Context value.
91
92Contexts are immutable, so it's fine to pass the same ctx to multiple
93calls that share the same deadline, cancellation signal, credentials,
94parent trace, etc.
95
Jaana B. Dogandcc731c2017-01-30 09:28:00 -080096## Copying
97
98To avoid unexpected aliasing, be careful when copying a struct from another package.
99For example, the bytes.Buffer type contains a `[]byte` slice and, as an optimization
100for small strings, a small byte array to which the slice may refer. If you copy a `Buffer`,
101the slice in the copy may alias the array in the original, causing subsequent method
102calls to have surprising effects.
103
104In general, do not copy a value of type `T` if its methods are associated with the
105pointer type, `*T`.
106
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600107## Declaring Empty Slices
108
Andrew Gerrand4d5a1b02017-02-02 12:06:50 +1100109When declaring an empty slice, prefer
110
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600111```go
112var t []string
113```
Andrew Gerrand4d5a1b02017-02-02 12:06:50 +1100114
115over
116
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600117```go
118t := []string{}
119```
120
Andrew Gerrand4d5a1b02017-02-02 12:06:50 +1100121The former declares a nil slice value, while the latter is non-nil but zero-length. They are functionally equivalenttheir `len` and `cap` are both zerobut the nil slice is the preferred style.
122
123Note that there are limited circumstances where a non-nil but zero-length slice is preferred, such as when encoding JSON objects (a `nil` slice encodes to `null`, while `[]string{}` encodes to the JSON array `[]`).
124
125When designing interfaces, avoid making a distinction between a nil slice and a non-nil, zero-length slice, as this can lead to subtle programming errors.
126
127For more discussion about nil in Go see Francesc Campoy's talk [Understanding Nil](https://www.youtube.com/watch?v=ynoY2xz-F8s).
Earl J. Wagner7dda73c2015-01-05 11:43:49 -0600128
Jaana B. Doganf11f8f72017-01-30 10:05:50 -0800129## Crypto Rand
Jaana B. Dogan9b339332017-01-30 09:32:22 -0800130
131Do not use package `math/rand` to generate keys, even throwaway ones.
132Unseeded, the generator is completely predictable. Seeded with `time.Nanoseconds()`,
133there are just a few bits of entropy. Instead, use `crypto/rand`'s Reader,
134and if you need text, print to hexadecimal or base64:
135
136``` go
137import (
138 "crypto/rand"
139 // "encoding/base64"
140 // "encoding/hex"
141 "fmt"
142)
143
144func Key() string {
145 buf := make([]byte, 16)
146 _, err := rand.Read(buf)
147 if err != nil {
148 panic(err) // out of randomness, should never happen
149 }
150 return fmt.Sprintf("%x", buf)
151 // or hex.EncodeToString(buf)
152 // or base64.StdEncoding.EncodeToString(buf)
153}
154```
155
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100156## Doc Comments
157
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700158All 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 +1100159
160## Don't Panic
161
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700162See 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 +1100163
164## Error Strings
165
Steve Carrupt6a3e3082016-11-24 09:49:46 +0900166Error 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 +1100167
Jaana B. Doganb181e782017-01-30 09:36:22 -0800168## Examples
169
170When adding a new package, include examples of intended usage: a runnable Example,
171or a simple test demonstrating a complete call sequence.
172
173Read more about [testable Example() functions](https://blog.golang.org/examples).
174
Jaana B. Dogan8590e712017-01-30 09:38:59 -0800175## Goroutine Lifetimes
176
177When you spawn goroutines, make it clear when - or whether - they exit.
178
179Goroutines can leak by blocking on channel sends or receives: the garbage collector
180will not terminate a goroutine even if the channels it is blocked on are unreachable.
181
182Even when goroutines do not leak, leaving them in-flight when they are no longer
183needed can cause other subtle and hard-to-diagnose problems. Sends on closed channels
184panic. Modifying still-in-use inputs "after the result isn't needed" can still lead
185to data races. And leaving goroutines in-flight for arbitrarily long can lead to
186unpredictable memory usage.
187
188Try to keep concurrent code simple enough that goroutine lifetimes are obvious.
189If that just isn't feasible, document when and why the goroutines exit.
Jaana B. Doganb181e782017-01-30 09:36:22 -0800190
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100191## Handle Errors
192
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700193See 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 +1100194
195## Imports
196
Jaana B. Dogan860d7842017-01-30 10:08:02 -0800197Avoid renaming imports except to avoid a name collision; good package names
198should not require renaming. In the event of collision, prefer to rename the most
199local or project-specific import.
200
201
202Imports are organized in groups, with blank lines between them.
203The standard library packages are always in the first group.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100204
nathany4d6a1bf2014-12-10 22:00:35 -0800205```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100206package main
207
208import (
Dave Day0d6986a2014-12-10 15:02:18 +1100209 "fmt"
210 "hash/adler32"
211 "os"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100212
Dave Day0d6986a2014-12-10 15:02:18 +1100213 "appengine/foo"
214 "appengine/user"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100215
Emmanuel T Odeke1f9a3842018-02-03 01:08:00 -0700216 "github.com/foo/bar"
217 "rsc.io/goversion/version"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100218)
219```
220
nathany4d6a1bf2014-12-10 22:00:35 -0800221<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 +1100222
223## Import Dot
224
225The import . form can be useful in tests that, due to circular dependencies, cannot be made part of the package being tested:
226
nathany4d6a1bf2014-12-10 22:00:35 -0800227```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100228package foo_test
229
230import (
Dave Day0d6986a2014-12-10 15:02:18 +1100231 "bar/testutil" // also imports "foo"
232 . "foo"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100233)
234```
235
236In 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.
237
Jaana B. Doganad8c4452017-01-30 10:15:18 -0800238## In-Band Errors
239
240In C and similar languages, it's common for functions to return values like -1
241or null to signal errors or missing results:
242
243```go
244// Lookup returns the value for key or "" if there is no mapping for key.
245func Lookup(key string) string
246
247// Failing to check a for an in-band error value can lead to bugs:
248Parse(Lookup(key)) // returns "parse failure for value" instead of "no value for key"
249```
250
251Go's support for multiple return values provides a better solution.
radbaron88a45ae2018-08-30 14:04:07 +0100252Instead of requiring clients to check for an in-band error value, a function should return
Jaana B. Doganad8c4452017-01-30 10:15:18 -0800253an additional value to indicate whether its other return values are valid. This return
254value may be an error, or a boolean when no explanation is needed.
255It should be the final return value.
256
257``` go
258// Lookup returns the value for key or ok=false if there is no mapping for key.
259func Lookup(key string) (value string, ok bool)
260```
261
262This prevents the caller from using the result incorrectly:
263
264``` go
265Parse(Lookup(key)) // compile-time error
266```
267
268And encourages more robust and readable code:
269
270``` go
271value, ok := Lookup(key)
272if !ok {
273 return fmt.Errorf("no value for %q", key)
274}
275return Parse(value)
276```
277
278This rule applies to exported functions but is also useful
279for unexported functions.
280
281Return values like nil, "", 0, and -1 are fine when they are
282valid results for a function, that is, when the caller need not
283handle them differently from other values.
284
285Some standard library functions, like those in package "strings",
286return in-band error values. This greatly simplifies string-manipulation
287code at the cost of requiring more diligence from the programmer.
Jaana B. Dogan5a81ed62017-01-30 21:58:59 -0800288In general, Go code should return additional values for errors.
Jaana B. Doganad8c4452017-01-30 10:15:18 -0800289
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100290## Indent Error Flow
291
nathany4d6a1bf2014-12-10 22:00:35 -0800292Try 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 +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
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100297} else {
Dave Day0d6986a2014-12-10 15:02:18 +1100298 // normal code
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100299}
300```
301
nathany4d6a1bf2014-12-10 22:00:35 -0800302Instead, write:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100303
nathany4d6a1bf2014-12-10 22:00:35 -0800304```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100305if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100306 // error handling
307 return // or continue, etc.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100308}
309// normal code
310```
311
Lachlan Cooper4434a5a2017-10-15 18:51:47 +1100312If the `if` statement has an initialization statement, such as:
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100313
nathany4d6a1bf2014-12-10 22:00:35 -0800314```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100315if x, err := f(); err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100316 // error handling
317 return
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100318} else {
Dave Day0d6986a2014-12-10 15:02:18 +1100319 // use x
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100320}
321```
322
323then this may require moving the short variable declaration to its own line:
324
nathany4d6a1bf2014-12-10 22:00:35 -0800325```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100326x, err := f()
327if err != nil {
Dave Day0d6986a2014-12-10 15:02:18 +1100328 // error handling
329 return
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100330}
331// use x
332```
333
334## Initialisms
335
Brad Fitzpatrick155654e2018-01-29 11:35:45 -0800336Words 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". As an example: ServeHTTP not ServeHttp. For identifiers with multiple initialized "words", use for example "xmlHTTPRequest" or "XMLHTTPRequest".
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100337
lylex4cc16f32018-02-10 22:35:40 +0800338This rule also applies to "ID" when it is short for "identifier", so write "appID" instead of "appId".
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100339
340Code generated by the protocol buffer compiler is exempt from this rule. Human-written code is held to a higher standard than machine-written code.
341
Jaana B. Dogan88f0e012017-01-30 10:20:32 -0800342## Interfaces
343
344Go interfaces generally belong in the package that uses values of the
345interface type, not the package that implements those values. The
346implementing package should return concrete (usually pointer or struct)
347types: that way, new methods can be added to implementations without
348requiring extensive refactoring.
349
350Do not define interfaces on the implementor side of an API "for mocking";
351instead, design the API so that it can be tested using the public API of
352the real implementation.
353
354Do not define interfaces before they are used: without a realistic example
355of usage, it is too difficult to see whether an interface is even necessary,
356let alone what methods it ought to contain.
357
358``` go
359package consumer // consumer.go
360
361type Thinger interface { Thing() bool }
362
363func Foo(t Thinger) string { … }
364```
365
366``` go
367package consumer // consumer_test.go
368
369type fakeThinger struct{ … }
370func (t fakeThinger) Thing() bool { … }
371
372if Foo(fakeThinger{…}) == "x" { … }
373```
374
375``` go
376// DO NOT DO IT!!!
377package producer
378
379type Thinger interface { Thing() bool }
380
381type defaultThinger struct{ … }
382func (t defaultThinger) Thing() bool { … }
383
384func NewThinger() Thinger { return defaultThinger{ … } }
385```
386
387Instead return a concrete type and let the consumer mock the producer implementation.
388``` go
389package producer
390
391type Thinger struct{ … }
392func (t Thinger) Thing() bool { … }
393
394func NewThinger() Thinger { return Thinger{ … } }
395```
396
397
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100398## Line Length
399
Jaana B. Dogan28407542017-01-30 10:55:16 -0800400There is no rigid line length limit in Go code, but avoid uncomfortably long lines.
401Similarly, don't add line breaks to keep lines short when they are more readable long--for example,
402if they are repetitive.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100403
Jaana B. Dogan28407542017-01-30 10:55:16 -0800404Most of the time when people wrap lines "unnaturally" (in the middle of function calls or
405function declarations, more or less, say, though some exceptions are around), the wrapping would be
406unnecessary if they had a reasonable number of parameters and reasonably short variable names.
407Long lines seem to go with long names, and getting rid of the long names helps a lot.
408
409In other words, break lines because of the semantics of what you're writing (as a general rule)
410and not because of the length of the line. If you find that this produces lines that are too long,
411then change the names or the semantics and you'll probably get a good result.
412
413This is, actually, exactly the same advice about how long a function should be. There's no rule
414"never have a function more than N lines long", but there is definitely such a thing as too long
415of a function, and of too stuttery tiny functions, and the solution is to change where the function
416boundaries are, not to start counting lines.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100417
418## Mixed Caps
419
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700420See 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 +1100421
Brad Fitzpatrick155654e2018-01-29 11:35:45 -0800422Also see [Initialisms](https://github.com/golang/go/wiki/CodeReviewComments#initialisms).
423
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100424## Named Result Parameters
425
426Consider what it will look like in godoc. Named result parameters like:
427
nathany4d6a1bf2014-12-10 22:00:35 -0800428```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100429func (n *Node) Parent1() (node *Node)
430func (n *Node) Parent2() (node *Node, err error)
431```
nathany4d6a1bf2014-12-10 22:00:35 -0800432
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100433will stutter in godoc; better to use:
nathany4d6a1bf2014-12-10 22:00:35 -0800434
435```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100436func (n *Node) Parent1() *Node
437func (n *Node) Parent2() (*Node, error)
438```
439
Jaana B. Dogan0df7fa52017-01-30 11:51:05 -0800440On the other hand, if a function returns two or three parameters of the same type,
441or if the meaning of a result isn't clear from context, adding names may be useful
442in some contexts. Don't name result parameters just to avoid declaring a var inside
443the function; that trades off a minor implementation brevity at the cost of
444unnecessary API verbosity.
445
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100446
447```go
Dave Day0d6986a2014-12-10 15:02:18 +1100448func (f *Foo) Location() (float64, float64, error)
449```
nathany4d6a1bf2014-12-10 22:00:35 -0800450
451is less clear than:
452
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100453```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100454// Location returns f's latitude and longitude.
455// Negative values mean south and west, respectively.
Dave Day0d6986a2014-12-10 15:02:18 +1100456func (f *Foo) Location() (lat, long float64, err error)
457```
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100458
Jaana B. Dogan0df7fa52017-01-30 11:51:05 -0800459Naked returns are okay if the function is a handful of lines. Once it's a medium
460sized function, be explicit with your return values. Corollary: it's not worth it
luantaobaec72a2018-07-05 22:45:33 +0800461to name result parameters just because it enables you to use named returns.
Jaana B. Dogan0df7fa52017-01-30 11:51:05 -0800462Clarity of docs is always more important than saving a line or two in your function.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100463
Jaana B. Dogan0df7fa52017-01-30 11:51:05 -0800464Finally, in some cases you need to name a result parameter in order to change
465it in a deferred closure. That is always OK.
466
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100467
468## Naked Returns
469
nathany812cb132014-12-10 22:35:33 -0800470See [Named Result Parameters](#named-result-parameters).
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100471
472## Package Comments
473
474Package comments, like all comments to be presented by godoc, must appear adjacent to the package clause, with no blank line.
475
nathany4d6a1bf2014-12-10 22:00:35 -0800476```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100477// Package math provides basic constants and mathematical functions.
478package math
479```
480
nathany4d6a1bf2014-12-10 22:00:35 -0800481```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100482/*
483Package template implements data-driven templates for generating textual
484output such as HTML.
485....
486*/
487package template
488```
489
Kenshi Kamataf9af9d42018-07-20 20:44:39 +0900490For "package main" comments, other styles of comment are fine after the binary name (and it may be capitalized if it comes first), For example, for a `package main` in the directory `seedgen` you could write:
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800491
Jaana B. Dogan4ac42e32017-01-30 11:04:39 -0800492``` go
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800493// Binary seedgen ...
Brad Fitzpatrickd2c439a2017-07-15 14:17:21 -0700494package main
495```
496or
Brad Fitzpatrick3c4eb232017-07-15 14:17:50 -0700497```go
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800498// Command seedgen ...
Brad Fitzpatrickd2c439a2017-07-15 14:17:21 -0700499package main
500```
501or
Brad Fitzpatrick3c4eb232017-07-15 14:17:50 -0700502```go
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800503// Program seedgen ...
Brad Fitzpatrickd2c439a2017-07-15 14:17:21 -0700504package main
505```
506or
Brad Fitzpatrick3c4eb232017-07-15 14:17:50 -0700507```go
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800508// The seedgen command ...
Brad Fitzpatrickd2c439a2017-07-15 14:17:21 -0700509package main
510```
511or
Brad Fitzpatrick3c4eb232017-07-15 14:17:50 -0700512```go
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800513// The seedgen program ...
Brad Fitzpatrickd2c439a2017-07-15 14:17:21 -0700514package main
515```
516or
Brad Fitzpatrick3c4eb232017-07-15 14:17:50 -0700517```go
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800518// Seedgen ..
Brad Fitzpatrickd2c439a2017-07-15 14:17:21 -0700519package main
Jaana B. Dogan8656afc2017-01-30 11:03:46 -0800520```
521
522These are examples, and sensible variants of these are acceptable.
523
524Note that starting the sentence with a lower-case word is not among the
525acceptable options for package comments, as these are publicly-visible and
526should be written in proper English, including capitalizing the first word
527of the sentence. When the binary name is the first word, capitalizing it is
528required even though it does not strictly match the spelling of the
529command-line invocation.
530
Dmitri Shuralyov2c403c22016-09-25 00:07:16 -0700531See https://golang.org/doc/effective_go.html#commentary for more information about commentary conventions.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100532
533## Package Names
534
Jaana B. Dogan17559282017-01-30 11:55:39 -0800535All references to names in your package will be done using the package name,
536so you can omit that name from the identifiers. For example, if you are in package chubby,
537you don't need type ChubbyFile, which clients will write as `chubby.ChubbyFile`.
538Instead, name the type `File`, which clients will write as `chubby.File`.
539Avoid meaningless package names like util, common, misc, api, types, and interfaces. See http://golang.org/doc/effective_go.html#package-names and
540http://blog.golang.org/package-names for more.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100541
542## Pass Values
543
Dave Day0d6986a2014-12-10 15:02:18 +1100544Don'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 +1100545
546## Receiver Names
547
Christopher Dunn4cb9dac2016-07-03 12:24:45 -0700548The 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 +1100549
550## Receiver Type
551
Kevin Gillette68ab16c2016-02-19 10:33:35 -0700552Choosing 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 +1100553
Jaana B. Dogan7ca7f1f2017-01-30 13:59:18 -0800554 * 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 +1100555 * If the method needs to mutate the receiver, the receiver must be a pointer.
556 * If the receiver is a struct that contains a sync.Mutex or similar synchronizing field, the receiver must be a pointer to avoid copying.
557 * 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.
558 * 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.
559 * 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.
560 * 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.
561 * Finally, when in doubt, use a pointer receiver.
562
Jaana B. Dogan220c5342017-01-30 14:01:00 -0800563## Synchronous Functions
564
565Prefer synchronous functions - functions which return their results directly or finish any callbacks or channel ops before returning - over asynchronous ones.
566
567Synchronous functions keep goroutines localized within a call, making it easier to reason about their lifetimes and avoid leaks and data races. They're also easier to test: the caller can pass an input and check the output without the need for polling or synchronization.
568
569If callers need more concurrency, they can add it easily by calling the function from a separate goroutine. But it is quite difficult - sometimes impossible - to remove unnecessary concurrency at the caller side.
570
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100571## Useful Test Failures
572
573Tests 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:
574
nathany4d6a1bf2014-12-10 22:00:35 -0800575```go
Dave Day0d6986a2014-12-10 15:02:18 +1100576if got != tt.want {
577 t.Errorf("Foo(%q) = %d; want %d", tt.in, got, tt.want) // or Fatalf, if test can't test anything more past this point
578}
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100579```
580
581Note 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.
582
nathany4d6a1bf2014-12-10 22:00:35 -0800583If that seems like a lot of typing, you may want to write a [[table-driven test|TableDrivenTests]].
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100584
585Another 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:
586
nathany4d6a1bf2014-12-10 22:00:35 -0800587```go
Dave Day0d6986a2014-12-10 15:02:18 +1100588func TestSingleValue(t *testing.T) { testHelper(t, []int{80}) }
589func TestNoValues(t *testing.T) { testHelper(t, []int{}) }
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100590```
591
592In any case, the onus is on you to fail with a helpful message to whoever's debugging your code in the future.
593
594## Variable Names
595
Hoon H8898bf22017-09-18 12:14:18 +0900596Variable 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`.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100597
Dave Day0d6986a2014-12-10 15:02:18 +1100598The 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.