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.

install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
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"
manifest: skills/Harmeet10000/skills/golang-naming/SKILL.md
source content

Community default. A company skill that explicitly supersedes

samber/cc-skills-golang@golang-naming
skill takes precedence.

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

ElementConventionExample
Packagelowercase, single word
json
,
http
,
tabwriter
Filelowercase, underscores OK
user_handler.go
Exported nameUpperCamelCase
ReadAll
,
HTTPClient
UnexportedlowerCamelCase
parseToken
,
userCount
Interfacemethod name +
-er
Reader
,
Closer
,
Stringer
StructMixedCaps noun
Request
,
FileHeader
ConstantMixedCaps (not ALL_CAPS)
MaxRetries
,
defaultTimeout
Receiver1-2 letter abbreviation
func (s *Server)
,
func (b *Buffer)
Error variable
Err
prefix
ErrNotFound
,
ErrTimeout
Error type
Error
suffix
PathError
,
SyntaxError
Constructor
New
(single type) or
NewTypeName
(multi-type)
ring.New
,
http.NewRequest
Boolean field
is
,
has
,
can
prefix on fields and methods
isReady
,
IsConnected()
Test function
Test
+ function name
TestParseToken
Acronymall caps or all lower
URL
,
HTTPServer
,
xmlParser
Variant: context
WithContext
suffix
FetchWithContext
,
QueryContext
Variant: in-place
In
suffix
SortIn()
,
ReverseIn()
Variant: error
Must
prefix
MustParse()
,
MustLoadConfig()
Option func
With
+ field name
WithPort()
,
WithLogger()
Enum (iota)type name prefix, zero-value = unknown
StatusUnknown
at 0,
StatusReady
Named returndescriptive, for docs only
(n int, err error)
Error stringlowercase (incl. acronyms), no punctuation
"image: unknown format"
,
"invalid id"
Import aliasshort, only on collision
mrand "math/rand"
,
pb "app/proto"
Format func
f
suffix
Errorf
,
Wrapf
,
Logf
Test table fields
got
/
expected
prefixes
input string
,
expected int

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:

    i
    for 3-line loops, longer names for package-level), single-letter receiver conventions (
    s
    for Server), acronym casing (URL not Url, HTTPServer not HttpServer), and boolean naming patterns (isReady, hasPrefix).

  • Functions, Methods & Options — Getter/setter patterns (Go omits

    Get
    so
    user.Name()
    reads naturally), constructor conventions (
    New
    or
    NewTypeName
    ), named returns (for documentation only), format function suffixes (
    Errorf
    ,
    Wrapf
    ), and functional options (
    WithPort
    ,
    WithLogger
    ).

  • Types, Constants & Errors — Interface naming (

    Reader
    ,
    Closer
    suffix with
    -er
    ), struct naming (nouns, MixedCaps), constants (MixedCaps, not ALL_CAPS), enums (type name prefix like
    StatusReady
    ), sentinel errors (
    ErrNotFound
    variables), error types (
    PathError
    suffix), and error message conventions (lowercase, no punctuation).

  • Test Naming — Test function naming (

    TestFunctionName
    ), table-driven test field conventions (
    input
    ,
    expected
    ), test helper naming, and subcase naming patterns.

Common Mistakes

MistakeFix
ALL_CAPS
constants
Go reserves casing for visibility, not emphasis — use
MixedCaps
(
MaxRetries
)
GetName()
getter
Go omits
Get
because
user.Name()
reads naturally at call sites. But
Is
/
Has
/
Can
prefixes are kept for boolean predicates:
IsHealthy() bool
not
Healthy() bool
Url
,
Http
,
Json
acronyms
Mixed-case acronyms create ambiguity (
HttpsUrl
— is it
Https+Url
?). Use all caps or all lower
this
or
self
receiver
Go methods are called frequently — use 1-2 letter abbreviation (
s
for
Server
) to reduce visual noise
util
,
helper
packages
These names say nothing about content — use specific names that describe the abstraction
http.HTTPClient
stuttering
Package name is always present at call site —
http.Client
avoids reading "HTTP" twice
user.NewUser()
constructor
Single primary type uses
New()
user.New()
avoids repeating the type name
connected bool
field
Bare adjective is ambiguous — use
isConnected
so the field reads as a true/false question
"invalid message ID"
error
Error strings must be fully lowercase including acronyms —
"invalid message id"
StatusReady
at iota 0
Zero value should be a sentinel —
StatusUnknown
at 0 catches uninitialized values
"not found"
error string
Sentinel errors should include the package name —
"mypackage: not found"
identifies the origin
userSlice
type-in-name
Types encode implementation detail —
users
describes what it holds, not how
Inconsistent receiver namesSwitching names across methods of the same type confuses readers — use one name consistently
snake_case
identifiers
Underscores conflict with Go's MixedCaps convention and tooling expectations — use
mixedCaps
Long names for short scopesName length should match scope —
i
is fine for a 3-line loop,
userIndex
is noise
Naming constants by valueValues change, roles don't —
DefaultPort
survives a port change,
Port8080
doesn't
FetchCtx()
context variant
WithContext
is the standard Go suffix —
FetchWithContext()
is instantly recognizable
sort()
in-place but no
In
Readers assume functions return new values.
SortIn()
signals mutation
parse()
panicking on error
MustParse()
warns callers that failure panics — surprises belong in the name
Mixing
With*
,
Set*
,
Use*
Consistency across the codebase —
With*
is the Go convention for functional options
Plural package namesGo convention is singular (
net/url
not
net/urls
) — keeps import paths consistent
Wrapf
without
f
suffix
The
f
suffix signals format-string semantics —
Wrapf
,
Errorf
tell callers to pass format args
Unnecessary import aliasesAliases add cognitive load. Only alias on collision —
mrand "math/rand"
Inconsistent concept namesUsing
user
/
account
/
person
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
    samber/cc-skills-golang@golang-code-style
    skill for broader formatting and style decisions
  • → See
    samber/cc-skills-golang@golang-structs-interfaces
    skill for interface naming depth and receiver design
  • → See
    samber/cc-skills-golang@golang-linter
    skill for automated enforcement (revive, predeclared, misspell, errname)