Fundamentals 24 min read

Master Go Naming: 30+ Rules for Clean, Idiomatic Code

This article presents a comprehensive, step‑by‑step analysis of Go naming conventions, explaining why each rule matters, illustrating each point with concrete code snippets and real‑world examples, and showing how to apply the guidelines to variables, functions, packages, structs, interfaces, errors, constants, enums and comments for truly clean Go code.

BirdNest Tech Talk
BirdNest Tech Talk
BirdNest Tech Talk
Master Go Naming: 30+ Rules for Clean, Idiomatic Code

Grady Booch’s influence on software engineering is highlighted, and his description of clean code is quoted before the article introduces a series of practical naming recommendations for Go developers.

Basic Naming Rules

The author starts by stating the problem: many newcomers write Go code that looks unidiomatic, such as oddly capitalized variable names or error messages with capital letters. The solution is to follow a set of concrete rules.

1. CamelCase for Exported Identifiers

Exported functions, types and variables must begin with an uppercase letter; unexported ones start with a lowercase letter. Example:

io.Copy()          // exported function
io.nopCloser()   // unexported type

2. Interface Names End with -er

Using the Reader, Writer, Closer and Stringer interfaces as examples, the article shows how the -er suffix clearly expresses the behavior the interface provides.

3. Short, Meaningful Variable Names

Loop counters can be i, j, k. Short‑lived variables may be wt (e.g., wt, ok := src.(WriterTo)). Meaningful names such as size := 32 * 1024 improve readability.

4. Package Names

Package names should be a single lower‑case word without underscores. Good examples are net, http, bytes. Bad examples like credentialprovider are discouraged.

5. Constant Naming

Constants use CamelCase, not ALL_CAPS. For example bufio.MaxScanTokenSize is preferred over MAX_CONNECTIONS.

6. Avoid Redundant Prefixes

Do not prepend ptr to pointer variables; the type already conveys pointer semantics. Example:

var user *User
name := user.Name   // no need for userPtr.Name

7. Receiver Names

Method receivers should be a single letter, usually the first letter of the type ( u for User, f for File).

8. Meaningful Intermediate Results

Instead of result1 and result2, use calculatedValue and processedValue, or more specific names like sum and average.

9. Boolean Function Prefixes

Functions returning bool should start with is, has or can (e.g., isValid, hasPermission, canAccess).

10. Verb‑Based Function Names

Functions should use the base verb form: convertToString(), calculateSum(), sendMessage(). Noun‑only names like conversion are discouraged, except for accessor methods that match the field name.

Struct Naming

Struct names should be nouns or noun phrases, such as User, Product, CustomerAddress. Avoid verbs or adjectives like RunningProcess. Prefer short, well‑known abbreviations (e.g., HTML, URL).

Interface Naming

Multi‑method interfaces use descriptive nouns ( ReadWriteCloser, HTTPHandler, Encoding). Single‑method interfaces may keep the -er form ( Reader, Writer). Prefixes I or Interface are avoided.

Type Alias Naming

Package‑level type aliases should be distinctive, e.g., NetworkRequest instead of a generic MyCustomRequest. Useful suffixes include Type, Alias, Func, List.

Embedded Field Naming

Anonymous embedding uses the embedded type name as the field name. Named embedding requires a meaningful field name, and naming conflicts are resolved by accessing the inner field explicitly ( outer.Inner.Value). Visibility follows the first‑letter case.

Error Naming

Package‑level sentinel errors start with Err or Error (e.g.,

var ErrClosedPipe = errors.New("io: read/write on closed pipe")

). Custom error types end with Error ( type InputError struct{...}). When wrapping errors, use fmt.Errorf("reading file %s: %w", filename, err) to preserve the original error semantics, and error strings should start with a lowercase letter and omit trailing punctuation.

Constant Naming

Constants use CamelCase and meaningful prefixes: enumeration constants ( ColorRed, ColorBlue), state constants ( StateActive), configuration constants ( ConfigMaxConnections), and magic‑number constants ( MaxUserNameLength, DefaultPageSize). Private constants may be lowercase but must be consistent within the package.

Enum Types

Define a base type (e.g., type Color int) and a grouped const block using iota. Provide a String() method for readable output, and avoid using zero as a valid enum value unless it represents an explicit "unknown" state.

Comments

File comments use block syntax, package comments start with "Package name ...". Function and method documentation begins with the function name, ends with a period, and may include examples. Type comments describe the purpose of the type. Inline and line‑end comments use // with a leading space. Consistent punctuation, capitalization, and indentation are emphasized.

By following this step‑by‑step analysis—identifying the readability problems, presenting concrete Go examples, explaining the rationale, and showing the preferred idiomatic forms—readers can transform novice Go code into clean, maintainable, and idiomatic Go programs.

programmingGobest practicesclean codeNaming Conventions
BirdNest Tech Talk
Written by

BirdNest Tech Talk

Author of the rpcx microservice framework, original book author, and chair of Baidu's Go CMC committee.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.