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
| Element | Convention | Example |
|---|
| Package | lowercase, single word | INLINECODE1 , http, INLINECODE3 |
| File |
lowercase, underscores OK |
user_handler.go |
| Exported name | UpperCamelCase |
ReadAll,
HTTPClient |
| Unexported | lowerCamelCase |
parseToken,
userCount |
| Interface | method name +
-er |
Reader,
Closer,
Stringer |
| Struct | MixedCaps noun |
Request,
FileHeader |
| Constant | MixedCaps (not ALL_CAPS) |
MaxRetries,
defaultTimeout |
| Receiver | 1-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 |
| Acronym | all 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 return | descriptive, for docs only |
(n int, err error) |
| Error string | lowercase (incl. acronyms), no punctuation |
"image: unknown format",
"invalid id" |
| Import alias | short, 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.
CODEBLOCK0
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.
CODEBLOCK1
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 ALLCAPS), 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
| Mistake | Fix |
|---|
| INLINECODE117 constants | Go reserves casing for visibility, not emphasis — use MixedCaps (MaxRetries) |
| INLINECODE120 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 names | Switching 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 scopes | Name length should match scope —
i is fine for a 3-line loop,
userIndex is noise |
| Naming constants by value | Values 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 names | Go 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 aliases | Aliases add cognitive load. Only alias on collision —
mrand "math/rand" |
| Inconsistent concept names | Using
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)
社区默认。 若公司技能明确覆盖了 samber/cc-skills-golang@golang-naming 技能,则以公司技能为准。
Go 命名约定
Go 偏好简短、可读的名称。大小写控制可见性——大写表示导出,小写表示未导出。所有标识符必须使用混合大小写(MixedCaps),绝不使用下划线。
清晰胜过巧妙。 — Go 谚语
设计架构,命名组件,记录细节。 — Go 谚语
若要忽略某条规则,只需在代码中添加注释。
快速参考
| 元素 | 约定 | 示例 |
|---|
| 包 | 小写,单个单词 | json,http,tabwriter |
| 文件 |
小写,允许下划线 | user_handler.go |
| 导出名称 | 大驼峰命名法 | ReadAll,HTTPClient |
| 未导出名称 | 小驼峰命名法 | parseToken,userCount |
| 接口 | 方法名 + -er | Reader,Closer,Stringer |
| 结构体 | 混合大小写名词 | Request,FileHeader |
| 常量 | 混合大小写(非全大写) | MaxRetries,defaultTimeout |
| 接收者 | 1-2 个字母缩写 | func (s
Server),func (b Buffer) |
| 错误变量 | Err 前缀 | ErrNotFound,ErrTimeout |
| 错误类型 | Error 后缀 | PathError,SyntaxError |
| 构造函数 | New(单一类型)或 NewTypeName(多类型) | ring.New,http.NewRequest |
| 布尔字段 |
字段和方法使用 is、has、can 前缀 | isReady,IsConnected() |
| 测试函数 | Test + 函数名 | TestParseToken |
| 缩写词 | 全大写或全小写 | URL,HTTPServer,xmlParser |
| 变体:上下文 | WithContext 后缀 | FetchWithContext,QueryContext |
| 变体:原地操作 | In 后缀 | SortIn(),ReverseIn() |
| 变体:错误 | Must 前缀 | MustParse(),MustLoadConfig() |
| 选项函数 | With + 字段名 | WithPort(),WithLogger() |
| 枚举(iota) | 类型名前缀,零值 = 未知 | StatusUnknown 在 0 位置,StatusReady |
| 命名返回值 | 描述性,仅用于文档 | (n int, err error) |
| 错误字符串 | 全小写(含缩写词),无标点 | image: unknown format,invalid id |
| 导入别名 | 简短,仅在冲突时使用 | mrand math/rand,pb app/proto |
| 格式化函数 | f 后缀 | Errorf,Wrapf,Logf |
| 测试表字段 | got/expected 前缀 | input string,expected int |
混合大小写
所有 Go 标识符必须使用 MixedCaps(或 mixedCaps)。绝不在标识符中使用下划线——唯一的例外是测试函数子用例(TestFoo_InvalidInput)、生成的代码以及操作系统/cgo 互操作。这是有实际意义的,而非装饰性的——Go 的导出机制依赖大小写,且工具链也假定全程使用混合大小写。
go
// ✓ 正确
MaxPacketSize
userCount
parseHTTPResponse
// ✗ 错误——这些约定与 Go 的导出机制和工具链预期冲突
MAXPACKETSIZE // C/Python 风格
maxpacketsize // 蛇形命名法
kMaxBufferSize // 匈牙利命名法
避免重复
Go 的调用点始终包含包名,因此在标识符中重复包名会浪费读者的时间——http.HTTPClient 迫使读者解析两次 HTTP。名称不得重复包名、类型名或周围上下文中已有的信息。
go
// 正确——调用点清晰
http.Client // 而非 http.HTTPClient
json.Decoder // 而非 json.JSONDecoder
user.New() // 而非 user.NewUser()
config.Parse() // 而非 config.ParseConfig()
// 在包 sqldb 中:
type Connection struct{} // 而非 DBConnection——db 已在包名中
// 反重复适用于所有导出类型,而不仅仅是主要结构体:
// 在包 dbpool 中:
type Pool struct{} // 而非 DBPool
type Status struct{} // 而非 PoolStatus——调用者写 dbpool.Status
type Option func(*Pool) // 而非 PoolOption
常被忽略的约定
这些约定是正确的但不明显——它们是命名错误最常见的来源:
构造函数命名: 当包只导出一个主要类型时,构造函数是 New(),而不是 NewTypeName()。这避免了重复——调用者写 apiclient.New() 而非 apiclient.NewClient()。仅当包有多个可构造类型时(如 http.NewRequest、http.NewServeMux),才使用 NewTypeName()。
布尔结构体字段: 未导出的布尔字段必须使用 is/has/can 前缀——isConnected、hasPermission,而不是裸的 connected 或 permission。导出的 getter 保留前缀:IsConnected() bool。这读起来自然像一个问题,并将布尔值与其他类型区分开来。
错误字符串完全小写——包括缩写词。 写 invalid message id 而非 invalid message ID,因为错误字符串经常与其他上下文拼接(fmt.Errorf(parsing token: %w, err)),混合大小写在句子中间看起来很奇怪。哨兵错误应包含包名作为前缀:errors.New(apiclient: not found)。
枚举零值: 始终在 iota 位置 0 放置一个显式的 Unknown/Invalid 哨兵。var s Status 会静默地变成 0——如果它映射到一个真实状态如 StatusReady,代码可能会表现得好像状态是故意选择的,而实际上并非如此。
子测试名称: t.Run() 中的表格驱动测试用例名称应为完全小写的描述性短语:valid id、empty input——而非 valid ID 或 Valid Input。
详细分类
有关完整规则、示例和理由,请参阅:
- - 包、文件和导入别名 — 包命名(单个单词、小写、无复数)、文件命名约定、导入别名模式(仅在冲突时使用以避免认知负担)以及目录结构。
- - 变量、布尔值、接收者和缩写词 — 基于作用域的命名(名称长度匹配作用域:3 行循环用 i,包级别用更长的名称)、单字母接收者约定(s 用于 Server)、缩写词大小写(URL 而非 Url,HTTPServer 而非 HttpServer)以及布尔命名模式(isReady、hasPrefix)。
- - 函数、方法和选项 — Getter/Setter 模式(Go 省略 Get,因此 user.Name() 读起来自然)、构造函数约定(New 或 NewTypeName)、命名返回值(仅用于文档)、格式化函数后缀(Errorf、Wrapf)以及函数选项(WithPort、WithLogger)。
- - 类型、常量和错误 — 接口命名(Reader、Closer 后缀 -er)、结构体命名(名词、混合大小写)、常量(混合大小写,非全大写)、枚举(类型名前缀如 StatusReady)、哨兵错误(ErrNotFound 变量)、错误类型(PathError 后缀)以及错误消息约定(小写、无标点)。
- - 测试命名 — 测试函数命名(TestFunctionName)、表格驱动测试字段约定(input、expected)、测试辅助函数命名以及子用例命名模式。
常见错误
| 错误 | 修正 |
|---|
| ALL_CAPS 常量 | Go 将大小写保留用于可见性,而非强调——使用 MixedCaps(MaxRetries) |
| GetName() getter |
Go 省略 Get