4.4 KiB
4.4 KiB
tags, create time
| tags | create time | ||||
|---|---|---|---|---|---|
|
2026-06-07 15:00 |
Go 语言命名规范
概述
Go 的命名哲学可以概括为一句话:一眼就能看懂,无需猜测。 本文总结包名、文件名、变量、函数、结构体、接口等所有标识符的命名规则。
正文
核心原则:大小写决定可见性
Go 没有 public / private 关键字,而是用首字母大小写来控制导出:
[!note] 📝 导出规则(最重要的一条)
- 大写开头 → 导出(exported),其他包可访问
- 小写开头 → 未导出(unexported),仅限本包内部使用
package mathClass
// Add 导出 → 其他包可调用
func Add(x, y int) int { return x + y }
// sub 未导出 → 仅在 mathClass 包内可用
func sub(x, y int) int { return x - y }
[!question] ❓ 思考 如果两个包分别导入了同一个第三方库,其中一个包的某个函数名和标准库重名,会发生什么?
包名
| 规则 | 示例 |
|---|---|
| 全小写,无下划线,简短有意义 | package domain / package service |
| 尽量与目录名一致 | 目录 user/ → package user |
| 不与标准库重名 | 不要用 package fmt |
文件名
- 全小写,可用下划线分隔(但建议少用)
- 头尾不能有下划线
- 避免与系统保留后缀冲突
[!warning] ⚠️ 特殊文件后缀
| 后缀 | 含义 |
|---|---|
_test.go |
测试文件,不编译到正常构建中 |
_windows.go / _linux.go |
平台特定文件,按 GOOS 条件编译 |
_386.go / _amd64.go |
架构特定文件,按 GOARCH 条件编译 |
[!tip] 💡 实用建议 虽然 Go 允许文件名含下划线,但为了整洁和避免踩坑,能不用就不用。多个单词用驼峰或连字符替代。
常量 & 枚举
采用驼峰命名,按功能分组:
const (
TypePage = "page"
// 页面类型
TypeHome = "home"
TypeSection = "section"
TypeTaxonomy = "taxonomy"
// 临时状态
TypeUnknown = "unknown"
)
枚举型常量应先定义类型,再用 iota 递增:
type CompareType int
const (
TypeEq CompareType = iota
TypeNe
TypeGt
TypeGe
TypeLt
TypeLe
)
[!tip] 💡 iota 分组技巧 用空行分隔不同用途的
iota序列,每个序列重新从 0 开始,可读性更好。
变量名
- 驼峰命名,首字母根据导出需求定大小写
- 布尔变量以
Is/Has/Can/Allow开头
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
[!warning] ⚠️ 常见陷阱 布尔变量不要起成
valid、ok这种含糊的名字——读者无法从名字判断它是什么状态的布尔值。
结构体名
驼峰命名,多字段时用多行声明更清晰:
type ServiceConfig struct {
Port string `json:"port"`
Address string `json:"address"`
}
config := ServiceConfig{
Port: "8080",
Address: "111.222.333.444",
}
[!tip] 💡 初始化风格 字段超过 2 个时,推荐用键值初始化(如上),比位置初始化更不易出错。
接口名
单方法接口的命名惯例是词根 + er:
| 接口 | 方法 | 含义 |
|---|---|---|
Reader |
Read(p []byte) (n int, err error) |
读取器 |
Writer |
Write(p []byte) (n int, err error) |
写入器 |
Closer |
Close() error |
关闭器 |
Seeker |
Seek(offset int64, whence int) (int64, error) |
定位器 |
type Reader interface {
Read(p []byte) (n int, err error)
}
[!note] 📝 为什么是 "er" 后缀? 这是 Go 社区约定俗成的惯例,源自 stdlib。遵循它能让你写的接口与其他库无缝对接(比如
io.Reader可以被任何fmt.Fprint消费)。
函数名
- 驼峰命名,首字母控制导出
- 名称应为动词或动词短语,简洁准确
func Save() {} // 导出:保存
func doJob() {} // 未导出:执行任务
func GetUser(id) {} // 导出:获取用户
[!warning] ⚠️ 注意 函数名不要与标准库函数重名,否则会造成混淆,甚至编译错误。