Get the FREE Ultimate OpenClaw Setup Guide →

go-naming

Scanned
npx machina-cli add skill cxuu/golang-skills/go-naming --openclaw
Files (1)
SKILL.md
8.2 KB

Go Naming Conventions

Normative: Core naming rules (MixedCaps, no underscores) are required per Google's canonical Go style guide. Advisory guidance provides best practices for clarity and maintainability.

Core Principle

Names should:

  • Not feel repetitive when used
  • Take context into consideration
  • Not repeat concepts that are already clear

Naming is more art than science—Go names tend to be shorter than in other languages.


MixedCaps (Required)

Normative: All Go identifiers must use MixedCaps.

Go uses MixedCaps or mixedCaps (camel case), never underscores (snake case).

// Good
MaxLength    // exported constant
maxLength    // unexported constant
userID       // variable
URLParser    // type with initialism

// Bad
MAX_LENGTH   // no snake_case
max_length   // no underscores
User_Name    // no underscores in names

Exceptions for Underscores

Names may contain underscores only in these cases:

  1. Test functions: TestFoo_InvalidInput, BenchmarkSort_LargeSlice
  2. Generated code: Package names only imported by generated code
  3. OS/cgo interop: Low-level libraries matching OS identifiers (rare)

Note: Filenames are not Go identifiers and may contain underscores.


Package Names

Normative: Packages must be lowercase with no underscores.

Package names must be:

  • Concise and lowercase only
  • No underscores (e.g., tabwriter not tab_writer)
  • Not likely to shadow common variables
// Good: user, oauth2, k8s, tabwriter
// Bad: user_service (underscores), UserService (uppercase), count (shadows var)

Avoid Uninformative Names

Advisory: Don't use generic package names.

Avoid names that tempt users to rename on import: util, common, helper, model, base. Prefer specific names: stringutil, httpauth, configloader.

Import Renaming

When renaming imports, the local name must follow package naming rules: import foopb "path/to/foo_go_proto" (not foo_pb with underscore).


Interface Names

Advisory: One-method interfaces use "-er" suffix.

By convention, one-method interfaces are named by the method name plus an -er suffix to construct an agent noun:

// Standard library examples
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }
type Formatter interface { Format(f State, verb rune) }
type CloseNotifier interface { CloseNotify() <-chan bool }

Honor canonical method names (Read, Write, Close, String) and their signatures. If your type implements a method with the same meaning as a well-known type, use the same name—call it String not ToString.


Receiver Names

Normative: Receivers must be short abbreviations, used consistently.

Receiver variable names must be:

  • Short (one or two letters)
  • Abbreviations for the type itself
  • Consistent across all methods of that type
Long Name (Bad)Better Name
func (tray Tray)func (t Tray)
func (info *ResearchInfo)func (ri *ResearchInfo)
func (this *ReportWriter)func (w *ReportWriter)
func (self *Scanner)func (s *Scanner)
// Good - consistent short receiver
func (c *Client) Connect() error
func (c *Client) Send(msg []byte) error
func (c *Client) Close() error

// Bad - inconsistent or long receivers
func (client *Client) Connect() error
func (cl *Client) Send(msg []byte) error
func (this *Client) Close() error

Constant Names

Normative: Constants use MixedCaps, never ALL_CAPS or K prefix.

// Good
const MaxPacketSize = 512
const defaultTimeout = 30 * time.Second

// Bad
const MAX_PACKET_SIZE = 512    // no snake_case
const kMaxBufferSize = 1024    // no K prefix

Name by Role, Not Value

Advisory: Constants should explain what the value denotes.

// Good - names explain the role
const MaxRetries = 3
const DefaultPort = 8080

// Bad - names just describe the value
const Three = 3
const Port8080 = 8080

Initialisms and Acronyms

Normative: Initialisms maintain consistent case throughout.

Initialisms (URL, ID, HTTP, API) should be all uppercase or all lowercase:

EnglishExportedUnexported
URLURLurl
IDIDid
HTTP/APIHTTPhttp
gRPC/iOSGRPC/IOSgRPC/iOS
// Good: HTTPClient, userID, ParseURL()
// Bad: HttpClient, orderId, ParseUrl()

Function and Method Names

Getters and Setters

Advisory: Don't use Get prefix for simple accessors.

If you have a field called owner (unexported), the getter should be Owner() (exported), not GetOwner(). The setter, if needed, is SetOwner():

// Good
owner := obj.Owner()
if owner != user {
    obj.SetOwner(user)
}

// Bad: c.GetName(), u.GetEmail(), p.GetID()

Use Compute or Fetch for expensive operations: db.FetchUser(id), stats.ComputeAverage().

Naming Conventions

Advisory: Use noun-like names for getters, verb-like names for actions.

// Noun-like for returning values
func (c *Config) JobName(key string) string
func (u *User) Permissions() []Permission

// Verb-like for actions
func (c *Config) WriteDetail(w io.Writer) error

Type Suffixes

When functions differ only by type, include type at the end: ParseInt(), ParseInt64(), AppendInt(), AppendInt64().

For a clear "primary" version, omit the type: Marshal() (primary), MarshalText() (variant).


Variable Names

Variable naming balances brevity with clarity. Key principles:

  • Scope-based length: Short names (i, v) for small scopes; longer, descriptive names for larger scopes
  • Single-letter conventions: Use familiar patterns (i for index, r/w for reader/writer)
  • Avoid type in name: Use users not userSlice, name not nameString
  • Prefix unexported globals: Use _ prefix for package-level unexported vars/consts to prevent shadowing
// Good - scope-appropriate naming
for i, v := range items { ... }           // small scope
pendingOrders := filterPending(orders)    // larger scope

// Good - unexported global with prefix
const _defaultPort = 8080

For detailed guidance: See references/VARIABLES.md


Avoiding Repetition

Go names should not feel repetitive when used. Consider the full context:

  • Package + symbol: widget.New() not widget.NewWidget()
  • Receiver + method: p.Name() not p.ProjectName()
  • Context + type: In package sqldb, use Connection not DBConnection
// Bad - repetitive
func (c *Config) WriteConfigTo(w io.Writer) error
package db
func LoadFromDatabase() error  // db.LoadFromDatabase()

// Good - concise
func (c *Config) WriteTo(w io.Writer) error
package db
func Load() error              // db.Load()

For detailed guidance: See references/REPETITION.md


Quick Reference

ElementRuleExample
Packagelowercase, no underscorespackage httputil
ExportedMixedCaps, starts uppercasefunc ParseURL()
UnexportedmixedCaps, starts lowercasefunc parseURL()
Receiver1-2 letter abbreviationfunc (c *Client)
ConstantMixedCaps, never ALL_CAPSconst MaxSize = 100
Initialismconsistent caseuserID, XMLAPI
Variablelength ~ scope sizei (small), userCount (large)

See Also

  • For interface design patterns: go-interfaces
  • For core style principles: go-style-core
  • For error handling patterns: go-error-handling
  • For testing best practices: go-testing
  • For defensive programming: go-defensive
  • For performance optimization: go-performance

Source

git clone https://github.com/cxuu/golang-skills/blob/main/skills/go-naming/SKILL.mdView on GitHub

Overview

This skill codifies Go naming conventions from Google and Uber: use MixedCaps for all identifiers, keep package names lowercase, and apply concise, context-aware names. It covers types, functions, methods, variables, constants, and interfaces, plus receiver naming and import renaming guidance to keep code idiomatic and maintainable.

How This Skill Works

It enforces naming rules across Go code: apply MixedCaps (no underscores) for all identifiers, with limited underscore exceptions; name packages lowercase and avoid shadowing; use -er suffix for one-method interfaces and ensure receivers are short and consistent; follow canonical method names like Read/Write/Close/String and avoid renaming through import tricks unless necessary.

When to Use It

  • Naming a new exported type or function in a Go module
  • Refactoring identifiers to improve clarity and consistency within a package
  • Choosing a concise, descriptive package name that is lowercase and underscore-free
  • Designing a one-method interface and applying the -er suffix appropriately
  • Ensuring consistent, short receiver names across all methods of a type

Quick Start

  1. Step 1: Identify the identifier category (type, func, var, const, or package) and whether it should be exported
  2. Step 2: Apply MixedCaps (no underscores) and use contextual, non-redundant names; respect initialisms like URL
  3. Step 3: For one-method interfaces, name with the method name plus the -er suffix and keep receivers short and consistent

Best Practices

  • Always use MixedCaps for identifiers; avoid snake_case unless you are in one of the allowed underscore cases
  • Keep receiver names short (one or two letters) and consistent across all methods of the type
  • Choose package names that are concise, lowercase, and descriptive; avoid generic terms like util or common
  • Prefer clear, context-aware names that reduce repetition and duplicative concepts
  • For one-method interfaces, use the method name plus the -er suffix (e.g., Reader, Writer)

Example Use Cases

  • MaxLength (exported constant) and maxLength (unexported constant/variable)
  • URLParser as a type using MixedCaps with initialisms
  • Reader/Writer interfaces that follow canonical method names
  • tabwriter as a lowercase package name example
  • func (c *Client) Connect() error using a short receiver name

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers