What's in a name?
October 2014

Andrew Gerrand
Google Inc.
adg@golang.org
@enneff
https://go.dev/


* Names matter

Readability is the defining quality of good code.

Good names are critical to readability.

This talk is about naming in Go.


* Good names

A good name is:

- Consistent (easy to guess),
- Short (easy to type),
- Accurate (easy to understand).


* A rule of thumb

The greater the distance between a name's declaration and its uses,
the longer the name should be.


* Use MixedCase

Names in Go should use `MixedCase`.

(Don't use `names_with_underscores`.)

Acronyms should be all capitals, as in `ServeHTTP` and `IDProcessor`.


* Local variables

Keep them short; long names obscure what the code _does_.

Common variable/type combinations may use really short names:

Prefer `i` to `index`.
Prefer `r` to `reader`.
Prefer `b` to `buffer`.

Avoid redundant names, given their context:

Prefer `count` to `runeCount` inside a function named `RuneCount`.
Prefer `ok` to `keyInMap` in the statement

	v, ok := m[k]

Longer names may help in long functions, or functions with many local variables.
(But often this just means you should refactor.)


* Bad

	func RuneCount(buffer []byte) int {
		runeCount := 0
		for index := 0; index < len(buffer); {
			if buffer[index] < RuneSelf {
				index++
			} else {
				_, size := DecodeRune(buffer[index:])
				index += size
			}
			runeCount++
		}
		return runeCount
	}


* Good

	func RuneCount(b []byte) int {
		count := 0
		for i := 0; i < len(b); {
			if b[i] < RuneSelf {
				i++
			} else {
				_, n := DecodeRune(b[i:])
				i += n
			}
			count++
		}
		return count
	}


* Parameters

Function parameters are like local variables,
but they also serve as documentation.

Where the types are descriptive, they should be short:

	func AfterFunc(d Duration, f func()) *Timer

	func Escape(w io.Writer, s []byte)

Where the types are more ambiguous, the names may provide documentation:

	func Unix(sec, nsec int64) Time

	func HasPrefix(s, prefix []byte) bool


* Return values

Return values on exported functions should only be named for documentation purposes.

These are good examples of named return values:

	func Copy(dst Writer, src Reader) (written int64, err error)

	func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)


* Receivers

Receivers are a special kind of argument.

By convention, they are one or two characters that reflect the receiver type,
because they typically appear on almost every line:

	func (b *Buffer) Read(p []byte) (n int, err error)

	func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)

	func (r Rectangle) Size() Point

Receiver names should be consistent across a type's methods.
(Don't use `r` in one method and `rdr` in another.)


* Exported package-level names

Exported names are qualified by their package names.

Remember this when naming exported variables, constants, functions, and types.

That's why we have `bytes.Buffer` and `strings.Reader`,
not `bytes.ByteBuffer` and `strings.StringReader`.


* Interface Types

Interfaces that specify just one method are usually just that function name with 'er' appended to it.

	type Reader interface {
		Read(p []byte) (n int, err error)
	}

Sometimes the result isn't correct English, but we do it anyway:

	type Execer interface {
		Exec(query string, args []Value) (Result, error)
	}

Sometimes we use English to make it nicer:

	type ByteReader interface {
		ReadByte() (c byte, err error)
	}

When an interface includes multiple methods, choose a name that accurately describes its purpose (examples: `net.Conn`, `http.ResponseWriter`, `io.ReadWriter`).


* Errors

Error types should be of the form `FooError`:

	type ExitError struct {
		...
	}

Error values should be of the form `ErrFoo`:

	var ErrFormat = errors.New("image: unknown format")


* Packages

Choose package names that lend meaning to the names they export.

Steer clear of `util`, `common`, and the like.


* Import paths

The last component of a package path should be the same as the package name.

	"compress/gzip" // package gzip

Avoid stutter in repository and package paths:

	"code.google.com/p/goauth2/oauth2" // bad; my fault

For libraries, it often works to put the package code in the repo root:

	"github.com/golang/oauth2" // package oauth2

Also avoid upper case letters (not all file systems are case sensitive).

* The standard library

Many examples in this talk are from the standard library.

The standard library is a great place to find good Go code.
Look to it for inspiration.

But be warned:

When the standard library was written, we were still learning.
Most of it we got right, but we made some mistakes.


* Conclusion

Use short names.

Think about context.

Use your judgment.


