Skillshub golang-naming
Go (Golang) naming conventions — covers packages, constructors, structs, interfaces, constants, enums, errors, booleans, receivers, getters/setters, functional options, acronyms, test functions, and subtest names. Use this skill when writing new Go code, reviewing or refactoring, choosing between naming alternatives (New vs NewTypeName, isConnected vs connected, ErrNotFound vs NotFoundError, StatusReady vs StatusUnknown at iota 0), debating Go package names (utils/helpers anti-patterns), or asking about Go naming best practices. Also trigger when the user mentions MixedCaps vs snake_case, ALL_CAPS constants, Get-prefix on getters, or error string casing. Do NOT use for general Go implementation questions that don't involve naming decisions.
git clone https://github.com/ComeOnOliver/skillshub
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/Harmeet10000/skills/golang-naming" ~/.claude/skills/comeonoliver-skillshub-golang-naming && rm -rf "$T"
skills/Harmeet10000/skills/golang-naming/SKILL.mdCommunity default. A company skill that explicitly supersedes
skill takes precedence.samber/cc-skills-golang@golang-naming
Go Naming Conventions
Go favors short, readable names. Capitalization controls visibility — uppercase is exported, lowercase is unexported. All identifiers MUST use MixedCaps, NEVER underscores.
"Clear is better than clever." — Go Proverbs
"Design the architecture, name the components, document the details." — Go Proverbs
To ignore a rule, just add a comment to the code.
Quick Reference
| Element | Convention | Example |
|---|---|---|
| Package | lowercase, single word | , , |
| File | lowercase, underscores OK | |
| Exported name | UpperCamelCase | , |
| Unexported | lowerCamelCase | , |
| Interface | method name + | , , |
| Struct | MixedCaps noun | , |
| Constant | MixedCaps (not ALL_CAPS) | , |
| Receiver | 1-2 letter abbreviation | , |
| Error variable | prefix | , |
| Error type | suffix | , |
| Constructor | (single type) or (multi-type) | , |
| Boolean field | , , prefix on fields and methods | , |
| Test function | + function name | |
| Acronym | all caps or all lower | , , |
| Variant: context | suffix | , |
| Variant: in-place | suffix | , |
| Variant: error | prefix | , |
| Option func | + field name | , |
| Enum (iota) | type name prefix, zero-value = unknown | at 0, |
| Named return | descriptive, for docs only | |
| Error string | lowercase (incl. acronyms), no punctuation | , |
| Import alias | short, only on collision | , |
| Format func | suffix | , , |
| Test table fields | / prefixes | , |
MixedCaps
All Go identifiers MUST use
MixedCaps (or mixedCaps). NEVER use underscores in identifiers — the only exceptions are test function subcases (TestFoo_InvalidInput), generated code, and OS/cgo interop. This is load-bearing, not cosmetic — Go's export mechanism relies on capitalization, and tooling assumes MixedCaps throughout.
// ✓ Good MaxPacketSize userCount parseHTTPResponse // ✗ Bad — these conventions conflict with Go's export mechanism and tooling expectations MAX_PACKET_SIZE // C/Python style max_packet_size // snake_case kMaxBufferSize // Hungarian notation
Avoid Stuttering
Go call sites always include the package name, so repeating it in the identifier wastes the reader's time —
http.HTTPClient forces parsing "HTTP" twice. A name MUST NOT repeat information already present in the package name, type name, or surrounding context.
// Good — clean at the call site http.Client // not http.HTTPClient json.Decoder // not json.JSONDecoder user.New() // not user.NewUser() config.Parse() // not config.ParseConfig() // In package sqldb: type Connection struct{} // not DBConnection — "db" is already in the package name // Anti-stutter applies to ALL exported types, not just the primary struct: // In package dbpool: type Pool struct{} // not DBPool type Status struct{} // not PoolStatus — callers write dbpool.Status type Option func(*Pool) // not PoolOption
Frequently Missed Conventions
These conventions are correct but non-obvious — they are the most common source of naming mistakes:
Constructor naming: When a package exports a single primary type, the constructor is
New(), not NewTypeName(). This avoids stuttering — callers write apiclient.New() not apiclient.NewClient(). Use NewTypeName() only when a package has multiple constructible types (like http.NewRequest, http.NewServeMux).
Boolean struct fields: Unexported boolean fields MUST use
is/has/can prefix — isConnected, hasPermission, not bare connected or permission. The exported getter keeps the prefix: IsConnected() bool. This reads naturally as a question and distinguishes booleans from other types.
Error strings are fully lowercase — including acronyms. Write
"invalid message id" not "invalid message ID", because error strings are often concatenated with other context (fmt.Errorf("parsing token: %w", err)) and mixed case looks wrong mid-sentence. Sentinel errors should include the package name as prefix: errors.New("apiclient: not found").
Enum zero values: Always place an explicit
Unknown/Invalid sentinel at iota position 0. A var s Status silently becomes 0 — if that maps to a real state like StatusReady, code can behave as if a status was deliberately chosen when it wasn't.
Subtest names: Table-driven test case names in
t.Run() should be fully lowercase descriptive phrases: "valid id", "empty input" — not "valid ID" or "Valid Input".
Detailed Categories
For complete rules, examples, and rationale, see:
-
Packages, Files & Import Aliasing — Package naming (single word, lowercase, no plurals), file naming conventions, import alias patterns (only use on collision to avoid cognitive load), and directory structure.
-
Variables, Booleans, Receivers & Acronyms — Scope-based naming (length matches scope:
for 3-line loops, longer names for package-level), single-letter receiver conventions (i
for Server), acronym casing (URL not Url, HTTPServer not HttpServer), and boolean naming patterns (isReady, hasPrefix).s -
Functions, Methods & Options — Getter/setter patterns (Go omits
soGet
reads naturally), constructor conventions (user.Name()
orNew
), named returns (for documentation only), format function suffixes (NewTypeName
,Errorf
), and functional options (Wrapf
,WithPort
).WithLogger -
Types, Constants & Errors — Interface naming (
,Reader
suffix withCloser
), struct naming (nouns, MixedCaps), constants (MixedCaps, not ALL_CAPS), enums (type name prefix like-er
), sentinel errors (StatusReady
variables), error types (ErrNotFound
suffix), and error message conventions (lowercase, no punctuation).PathError -
Test Naming — Test function naming (
), table-driven test field conventions (TestFunctionName
,input
), test helper naming, and subcase naming patterns.expected
Common Mistakes
| Mistake | Fix |
|---|---|
constants | Go reserves casing for visibility, not emphasis — use () |
getter | Go omits because reads naturally at call sites. But // prefixes are kept for boolean predicates: not |
, , acronyms | Mixed-case acronyms create ambiguity ( — is it ?). Use all caps or all lower |
or receiver | Go methods are called frequently — use 1-2 letter abbreviation ( for ) to reduce visual noise |
, packages | These names say nothing about content — use specific names that describe the abstraction |
stuttering | Package name is always present at call site — avoids reading "HTTP" twice |
constructor | Single primary type uses — avoids repeating the type name |
field | Bare adjective is ambiguous — use so the field reads as a true/false question |
error | Error strings must be fully lowercase including acronyms — |
at iota 0 | Zero value should be a sentinel — at 0 catches uninitialized values |
error string | Sentinel errors should include the package name — identifies the origin |
type-in-name | Types encode implementation detail — describes what it holds, not how |
| Inconsistent receiver names | Switching names across methods of the same type confuses readers — use one name consistently |
identifiers | Underscores conflict with Go's MixedCaps convention and tooling expectations — use |
| Long names for short scopes | Name length should match scope — is fine for a 3-line loop, is noise |
| Naming constants by value | Values change, roles don't — survives a port change, doesn't |
context variant | is the standard Go suffix — is instantly recognizable |
in-place but no | Readers assume functions return new values. signals mutation |
panicking on error | warns callers that failure panics — surprises belong in the name |
Mixing , , | Consistency across the codebase — is the Go convention for functional options |
| Plural package names | Go convention is singular ( not ) — keeps import paths consistent |
without suffix | The suffix signals format-string semantics — , tell callers to pass format args |
| Unnecessary import aliases | Aliases add cognitive load. Only alias on collision — |
| Inconsistent concept names | Using // for the same concept forces readers to track synonyms — pick one name |
Enforce with Linters
Many naming convention issues are caught automatically by linters:
revive, predeclared, misspell, errname. See samber/cc-skills-golang@golang-linter skill for configuration and usage.
Cross-References
- → See
skill for broader formatting and style decisionssamber/cc-skills-golang@golang-code-style - → See
skill for interface naming depth and receiver designsamber/cc-skills-golang@golang-structs-interfaces - → See
skill for automated enforcement (revive, predeclared, misspell, errname)samber/cc-skills-golang@golang-linter