168 lines
4.4 KiB
Markdown
168 lines
4.4 KiB
Markdown
---
|
|
tags: [go, golang, go基础语法, go命名规范]
|
|
create time: 2026-06-07 15:00
|
|
---
|
|
|
|
# Go 语言命名规范
|
|
|
|
## 概述
|
|
|
|
Go 的命名哲学可以概括为一句话:**一眼就能看懂,无需猜测。** 本文总结包名、文件名、变量、函数、结构体、接口等所有标识符的命名规则。
|
|
|
|
## 正文
|
|
|
|
### 核心原则:大小写决定可见性
|
|
|
|
Go 没有 `public` / `private` 关键字,而是用**首字母大小写**来控制导出:
|
|
|
|
> [!note] 📝 导出规则(最重要的一条)
|
|
> - **大写开头** → 导出(exported),其他包可访问
|
|
> - **小写开头** → 未导出(unexported),仅限本包内部使用
|
|
|
|
```go
|
|
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 允许文件名含下划线,但为了整洁和避免踩坑,**能不用就不用**。多个单词用驼峰或连字符替代。
|
|
|
|
### 常量 & 枚举
|
|
|
|
采用驼峰命名,按功能分组:
|
|
|
|
```go
|
|
const (
|
|
TypePage = "page"
|
|
|
|
// 页面类型
|
|
TypeHome = "home"
|
|
TypeSection = "section"
|
|
TypeTaxonomy = "taxonomy"
|
|
|
|
// 临时状态
|
|
TypeUnknown = "unknown"
|
|
)
|
|
```
|
|
|
|
枚举型常量应先定义类型,再用 `iota` 递增:
|
|
|
|
```go
|
|
type CompareType int
|
|
|
|
const (
|
|
TypeEq CompareType = iota
|
|
TypeNe
|
|
TypeGt
|
|
TypeGe
|
|
TypeLt
|
|
TypeLe
|
|
)
|
|
```
|
|
|
|
> [!tip] 💡 iota 分组技巧
|
|
> 用空行分隔不同用途的 `iota` 序列,每个序列重新从 0 开始,可读性更好。
|
|
|
|
### 变量名
|
|
|
|
- 驼峰命名,首字母根据导出需求定大小写
|
|
- **布尔变量**以 `Is` / `Has` / `Can` / `Allow` 开头
|
|
|
|
```go
|
|
var isExist bool
|
|
var hasConflict bool
|
|
var canManage bool
|
|
var allowGitHook bool
|
|
```
|
|
|
|
> [!warning] ⚠️ 常见陷阱
|
|
> 布尔变量不要起成 `valid`、`ok` 这种含糊的名字——读者无法从名字判断它是什么状态的布尔值。
|
|
|
|
### 结构体名
|
|
|
|
驼峰命名,多字段时用多行声明更清晰:
|
|
|
|
```go
|
|
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)` | 定位器 |
|
|
|
|
```go
|
|
type Reader interface {
|
|
Read(p []byte) (n int, err error)
|
|
}
|
|
```
|
|
|
|
> [!note] 📝 为什么是 "er" 后缀?
|
|
> 这是 Go 社区约定俗成的惯例,源自 stdlib。遵循它能让你写的接口与其他库无缝对接(比如 `io.Reader` 可以被任何 `fmt.Fprint` 消费)。
|
|
|
|
### 函数名
|
|
|
|
- 驼峰命名,首字母控制导出
|
|
- 名称应为**动词或动词短语**,简洁准确
|
|
|
|
```go
|
|
func Save() {} // 导出:保存
|
|
func doJob() {} // 未导出:执行任务
|
|
func GetUser(id) {} // 导出:获取用户
|
|
```
|
|
|
|
> [!warning] ⚠️ 注意
|
|
> 函数名不要与标准库函数重名,否则会造成混淆,甚至编译错误。
|
|
|
|
## 关联笔记
|
|
- [[hzh/GolangStar/Go语言基础/Go语言代码结构]]
|
|
- [[hzh/GolangStar/Go语言基础/Go语言变量]]
|
|
- [[hzh/GolangStar/Go语言基础/Go语言结构体]]
|