Clean code in Go · 3 MIN READ

Names that expose responsibility

Make a caller understand units, results and ownership from the API.

Make a caller understand units, results and ownership from the API. Names should reduce guesses at the call site. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.

Clean Go · A MAP OF THE IDEA

  1. Caller reads the contract
  2. Typed input exposes units
  3. Result makes the decision explicit

Useful when

  • Different units or meanings can be confused
  • An API is read outside its implementation

Watch out

  • Verbosity can hide a simple idea
  • Naming cannot fix mixed responsibilities

Implementation & operation cost: Low

01

The design decision

Names should reduce guesses at the call site. Include units when a number otherwise has several meanings, avoid repeating the package name in every exported identifier, and replace vague helpers with a responsibility such as parsing a duration or calculating a quote.

02

A complete Go example

Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.

go
package main

import (
	"fmt"
	"time"
)

type RetryPolicy struct {
	Delay       time.Duration
	MaxAttempts int
}

func NextDelay(policy RetryPolicy, attempt int) (time.Duration, bool) {
	if attempt >= policy.MaxAttempts {
		return 0, false
	}
	return policy.Delay, true
}

func main() {
	delay, retry := NextDelay(RetryPolicy{Delay: 250 * time.Millisecond, MaxAttempts: 3}, 1)
	fmt.Println(delay, retry)
}

// Output:
// 250ms true
Read the code

Delay has a duration type rather than an undocumented integer unit. NextDelay returns both a value and a decision, so zero is not overloaded to mean stop. Attempt numbering must still be documented: this example uses a zero-based attempt index.

03

Tradeoffs and the simpler alternative

Choose brevity in small scopes and precision at boundaries. A long name cannot repair a confused responsibility. Keep comments for contracts, assumptions and reasons; let gofmt handle alignment rather than preserving a personal formatting convention.

04

Name the contract, not the implementation accident

Prefer ReserveStock to Process and OrderID to a bare string whose meaning changes by call site. Include units when a numeric type does not make them clear; use time.Duration rather than an undocumented integer timeout. A name should tell the caller whether a method mutates, blocks or acquires a resource. Avoid repeating a package name in every exported identifier when the qualified call already supplies it. Short names remain useful for small, obvious scopes such as a loop index.

05

Make invalid states harder to pass

A named type can distinguish CustomerID from OrderID at compile time, but a string alias alone does not validate content. Validate input at the boundary and construct a value that has a documented invariant. Avoid boolean flag arguments whose call-site meaning is unclear; separate operations or a small options type can be easier to read. Do not replace every primitive with a wrapper: choose types where confusing two values or forgetting validation has a real cost.

06

Review names with a caller and a failure

Read a call without opening its implementation. Can you tell whether the result may be partial, who owns returned bytes and which error means missing? Rename or document the contract when the answer is unclear. Test a malformed ID and an empty value before claiming a constructor makes invalid states impossible. During a rename, keep public compatibility or provide a migration path; internal clarity and external API stability are separate concerns.

TAKE THIS WITH YOU

Reduce ambiguity with types and precise API names. Choose brevity in small scopes and precision at boundaries. A long name cannot repair a confused responsibility. Keep comments for contracts, assumptions and reasons; let gofmt handle alignment rather than preserving a personal formatting convention.

Check your understanding

Which statement best describes Names that expose responsibility?

Go to the source

Progress stays in this browser. No account needed.