关于 golang-naming
面向 Go 开发者和编码 Agent 的命名规范技能,涵盖包、类型、标识符、错误和测试命名。通过规则与示例说明命名方式,并提供重命名和静态检查指引。
主要功能
- 01MixedCaps 与缩写大小写规则
- 02包、文件和标识符命名规范
- 03构造函数、接收者与布尔值命名
- 04错误、枚举和测试命名模式
- 05命名问题的 Linter 指引
适用场景
- 01检查 Go 标识符是否违反规范
- 02为新的 Go API 和类型选择名称
- 03统一错误和枚举的命名方式
- 04规划代码库范围的命名修改
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ samber/ cc-skills-golang --skill golang-naming安装后在 Claude Code 中输入/golang-naming确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/functions-methods.mdidentifiers.mdpackages-files.mdtesting.mdtypes-errors.md详细介绍
社区默认规范。 明确取代
samber/cc-skills-golang@golang-naming技能的公司技能优先。
Go 命名约定
Go 偏好简短、易读的名称。大小写决定可见性——大写开头表示已导出,小写开头表示未导出。所有标识符 MUST 使用 MixedCaps,绝 NEVER 使用下划线。
“清晰胜过巧妙。”——Go Proverbs
“设计架构,命名组件,记录细节。”——Go Proverbs
若要忽略某条规则,只需在代码中添加注释。
快速参考
| 元素 | 约定 | 示例 |
|---|---|---|
| 包 | 全小写,单个单词;测试文件可以使用 _test 后缀 | json、http、tabwriter、http_test |
| 文件 | 全小写,可以使用下划线 | user_handler.go |
| 已导出名称 | UpperCamelCase | ReadAll、HTTPClient |
| 未导出名称 | lowerCamelCase | parseToken、userCount |
| 接口 | 方法名 + -er | Reader、Closer、Stringer |
| 结构体 | MixedCaps 名词 | Request、FileHeader |
| 常量 | MixedCaps(不是 ALL_CAPS) | 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 |
MixedCaps
所有 Go 标识符 MUST 使用 MixedCaps(或 mixedCaps)。标识符中绝 NEVER 使用下划线——唯一例外是测试函数子用例(TestFoo_InvalidInput)、生成的代码以及 OS/cgo 互操作。这是关键要求,并非外观问题——Go 的导出机制依赖大小写,工具也默认全面使用 MixedCaps。
// ✓ 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
避免名称重复
Go 的调用处始终包含包名,因此在标识符中重复包名会浪费读者的时间——http.HTTPClient 会让人不得不解析两次“HTTP”。名称 MUST NOT 重复包名、类型名或周边上下文中已有的信息。
// 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
经常忽略的惯例
这些惯例虽然正确,却不太直观——它们是最常见的命名错误来源:
构造函数命名: 当一个包只导出一种主要类型时,构造函数应命名为 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——如果 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)。 -
类型、常量与错误 — 接口命名(以
-er结尾的后缀,如Reader、Closer)、结构体命名(名词、MixedCaps)、常量(MixedCaps,而非 ALL_CAPS)、枚举(使用类型名前缀,如StatusReady)、哨兵错误(ErrNotFound变量)、错误类型(以PathError作为后缀)以及错误消息惯例(全小写,不加标点)。 -
测试命名 — 测试函数命名(
TestFunctionName)、表驱动测试字段惯例(input、expected)、测试辅助函数命名以及子用例命名模式。
常见错误
| 错误 | 修正 |
|---|---|
ALL_CAPS 常量 | Go 使用大小写表示可见性,而非强调——请使用 MixedCaps(MaxRetries) |
GetName() getter | Go 省略 Get,因为在调用处写成 user.Name() 更自然。但布尔谓词会保留 Is/Has/Can 前缀:使用 IsHealthy() bool,而非 Healthy() bool |
Url、Http、Json 等缩写 | 混合大小写的缩写会造成歧义(HttpsUrl——这是 Https+Url 吗?)。请全部使用大写或全部使用小写 |
this 或 self 接收者 | Go 方法调用频繁——请使用 1-2 个字母的缩写(Server 使用 s),以减少视觉干扰 |
util、helper 包 | 这些名称无法说明内容——请使用能描述抽象的具体名称 |
http.HTTPClient 重复命名 | 包名总会出现在调用处——http.Client 可避免重复读取“HTTP” |
user.NewUser() 构造函数 | 单一主要类型使用 New()——user.New() 可避免重复类型名称 |
connected bool 字段 | 单独的形容词含义模糊——请使用 isConnected,让字段读起来像一个是/否问题 |
"invalid message ID" 错误 | 错误字符串必须全部使用小写,包括缩写——"invalid message id" |
从 iota 0 开始的 StatusReady | 零值应作为哨兵值——在 0 处使用 StatusUnknown,以捕获未初始化的值 |
"not found" 错误字符串 | 哨兵错误应包含包名——"mypackage: not found" 可标明来源 |
名称中包含实现细节的 userSlice 类型 | 类型应描述内容,而非实现细节——users 描述其所保存的内容 |
| 不一致的接收者名称 | 同一类型的方法使用不同名称会让读者困惑——请始终使用同一个名称 |
snake_case 标识符 | 下划线与 Go 的 MixedCaps 约定及工具预期相冲突——请使用 mixedCaps |
| 短作用域使用长名称 | 名称长度应与作用域相称——3 行循环中用 i 很合适,userIndex 则显得冗余 |
| 根据值命名常量 | 值会变,作用不变——端口变更后 DefaultPort 仍然适用,Port8080 则不适用 |
FetchCtx() 上下文变体 | WithContext 是 Go 的标准后缀——FetchWithContext() 一看便知其含义 |
sort() 原地排序却没有 In | 读者会认为函数返回新值。SortIn() 表示会修改原值 |
parse() 出错时触发 panic | MustParse() 会提醒调用者失败时会触发 panic——意外行为应体现在名称中 |
混用 With*、Set*、Use* | 保持整个代码库的一致性——With* 是 Go 函数选项的惯例 |
| 复数包名 | Go 的惯例是使用单数(net/url 而非 net/urls)——这样导入路径更一致 |
Wrapf 没有 f 后缀 | f 后缀表示格式字符串语义——Wrapf、Errorf 会提示调用者传入格式参数 |
| 不必要的导入别名 | 别名会增加认知负担。仅在名称冲突时使用别名——mrand "math/rand" |
| 概念名称不一致 | 同一概念使用 user/account/person 会迫使读者辨别多个同义词——请选用一个名称 |
应用这些修正意味着要重命名现有标识符——→ 请参阅 samber/cc-skills-golang@golang-gopls 技能,以安全地完成重命名:它会在整个工作区中更新每个调用处,并拒绝会破坏接口满足性的重命名;而 grep/sed 或基于 Edit 的手动重命名会悄然漏掉这类问题。
使用 Linter 强制执行
许多命名约定问题都可由 Linter 自动发现:revive、predeclared、misspell、errname。有关配置和用法,请参阅 samber/cc-skills-golang@golang-lint 技能。
交叉引用
- → 有关更全面的格式与风格决策,请参阅
samber/cc-skills-golang@golang-code-style技能 - → 有关接口命名深度与接收者设计,请参阅
samber/cc-skills-golang@golang-structs-interfaces技能 - → 有关自动化检查(revive、predeclared、misspell、errname),请参阅
samber/cc-skills-golang@golang-lint技能 - → 有关应用命名修复时如何安全重命名,请参阅
samber/cc-skills-golang@golang-gopls技能 - → 确定要将标识符重命名为何之后,有关如何大规模安全地应用重命名(gopls Rename/Inline、影响范围映射、分阶段 PR 工作流),请参阅
samber/cc-skills-golang@golang-refactoring技能