命名规则规范

Go 语言命名规范

你好,欢迎来到 Go 语言的世界!在你开始编写惊艳的代码之前,我们先来聊一个看似简单却至关重要的话题:命名

好的命名就像是给你的代码画一张清晰的地图,不仅你自己看着舒服,将来和其他人合作时,别人也能轻松看懂你的“地图”,快速上手。Go 语言有一套简洁、优雅的命名哲学,掌握了它,你的代码会变得更加专业。

别担心,这不复杂,让我们一步步来拆解。

核心总则:大道至简

记住这几条黄金法则,你就掌握了 Go 命名的精髓:

  1. 简洁直观:名字要能一眼看懂是干嘛的。比如 calculateScore 就比 calcScr 好一万倍。
  2. 驼峰命名法 (CamelCase):这是 Go 的标准姿势。当一个名字由多个单词组成时,把它们拼在一起,每个单词的首字母大写,就是大驼峰CamelCasePascalCase);如果第一个单词的首字母小写,那就是小驼峰camelCase)。
  3. 首字母大小写 = “可见性”:这是 Go 最最最重要的特性!如果一个名字(比如变量、函数、结构体)的首字母是大写的,就好像你在对大家说:“嘿,这个东西你们谁都能用!”。这在 Go 里叫导出 (Exported),是公开的 (public)。反之,如果是小写字母开头,就等于在说:“这是我的私人用品,别碰!”,这叫**未导出 (unexported),是私有的 (private)**。
  4. 避免无意义的缩写:除非是像 ID, URL, HTTP 这样全世界程序员都认识的“暗号”,否则别自己创造缩写。没人喜欢猜谜语。

1. 包 (Package) 命名:你的代码工具箱

什么是包? 你可以把“包”想象成一个专门放某一类工具的工具箱。比如,一个叫 cache 的包,里面可能就放满了各种和缓存操作相关的工具(函数、结构体等)。

命名规则:

  • 一律小写:简单、干净。
  • 简短且有意义:用一个单词说清楚这个工具箱的用途。
  • 不要用下划线 _ 或驼峰:这是约定俗成的规矩。
  • 不要和标准库重名:你总不想把你自己的 http 包和 Go 官方的 http 包搞混吧?

示例:

Go

1
2
3
4
5
6
7
8
// 导入一个处理字符串的标准库包
import "strings"

// 导入一个处理网络请求的标准库包
import "net/http"

// 导入一个你项目中自己写的,用于日志记录的包
import "github.com/your-project/logger"

推荐net, http, cache, logger, config避免Net, my_cache, stringUtils, LoggerPackage


2. 文件命名:整理你的工具

什么是文件? 如果说包是工具箱,那文件就是工具箱里的一个个小格子,用来分类存放你的工具。

命名规则:

  • 全小写:保持队形。
  • 用下划线 _ 分隔单词:如果文件名需要多个单词,用下划线连接,这在 Go 文件命名中是允许且常见的。
  • 功能导向:文件名要说清楚这个文件是干嘛的。
  • 测试文件是特殊的:所有测试代码都必须放在以 _test.go 结尾的文件里,这是 Go 的硬性规定。

示例:

http_server.go // 存放 HTTP 服务器相关代码 user_model.go // 存放用户数据模型相关代码 utils.go // 存放一些通用的小工具函数

http_server_test.go // 这是上面 http_server.go 对应的测试文件


3. 变量与常量:存放数据的盒子

命名规则:

  • **小驼峰命名 (camelCase)**:对于函数内部的局部变量,或者包内私有的变量,统一使用小驼峰。
  • 首字母大写 = 导出:如果你想让一个变量或常量在项目其他包中也能被使用,就把它首字母大写。
  • 短小精悍:特别是对于局部变量,名字短一点没关系。比如在循环里,大家都默认用 i, j, k
  • **常量组 iota**:当需要定义一组递增的常量(比如枚举)时,使用 iota 这个神奇的关键字,它能让你的代码更简洁。通常会给这类常量加上一个共同的前缀。

示例:

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 这是一个只能在当前包使用的私有变量
var userCount int

// 这是一个可以在任何地方使用的公开常量
const MaxConnections = 100

// 一个简单的循环变量
for i := 0; i < 5; i++ {
// ...
}

// 使用 iota 定义一组状态常量,它们的值会从 0 开始自动递增
type Status int
const (
StatusPending Status = iota // 值为 0
StatusRunning // 值为 1
StatusSuccess // 值为 2
StatusFailed // 值为 3
)

4. 函数与方法:执行动作的指令

什么是函数/方法? 函数是一段可以执行特定任务的代码。方法是“绑定”在某个特定类型(如结构体)上的函数。

命名规则:

  • **小驼峰命名 (camelCase)**:和变量一样,私有函数用小驼峰。
  • 首字母大写 = 导出:公开的、可以给别人用的函数,首字母大写。
  • 像动词一样:函数名最好是一个动作,比如 GetUser, CalculatePrice, DeleteUser

示例:

Go

1
2
3
4
5
6
7
8
9
10
// 这是一个私有函数,只能在包内调用,用来创建一个新的服务器实例
func newServer(port int) *Server {
// ...
}

// 这是一个公开的方法,绑定在 *Server 类型上,用来启动服务器
// 任何能拿到 Server 实例的地方都可以调用它
func (s *Server) Start() error {
// ...
}

5. 结构体与接口:代码的蓝图与契约

什么是结构体 (Struct)? 结构体是自定义的数据类型“蓝图”。比如,你可以定义一个 User 结构体,它有 IDNameEmail 这些属性。

什么是接口 (Interface)? 接口是一种“契约”或“规范”。它只定义了“需要做什么”(有哪些方法),但不关心“具体怎么做”。比如,一个 Reader 接口规定了任何实现它的类型都必须有一个 Read 方法。

命名规则:

  • **结构体:大驼峰 (CamelCase)**。它是一个类型,所以通常用大驼峰。
  • 接口:通常以 -er 结尾。这是一个非常 Go-Style 的习惯!如果一个接口定义了一种能力,就用 “能力动词 + er” 来命名。比如能 Read 的就是 Reader,能 Write 的就是 Writer。如果接口包含多个方法,也可以用一个名词来命名,如 http.Handler

示例:

Go

1
2
3
4
5
6
7
8
9
10
11
// 定义一个公开的 User 结构体
type User struct {
ID int
Name string
}

// 定义一个“可读取”的接口契约
// 任何类型只要实现了 Read 方法,就被认为是一个 Reader
type Reader interface {
Read(p []byte) (n int, err error)
}

6. 处理常见缩写:不成文的规矩

对于像 URL, ID, HTTP, API, JSON 这类广为人知的缩写,有一个约定俗成的规则:保持它们全大写

错误示范UrlParser, HttpServer 正确姿势URLParser, HTTPServer

这让代码在视觉上更容易区分出这些常见的技术术语。

示例:

Go

1
2
3
4
5
6
var userID int
var defaultURL string

type HTTPServer struct {
// ...
}

7. 错误 (Error) 命名:清晰地告诉我们“出错了”

在 Go 中,错误处理非常重要。好的错误命名能让调试事半功倍。

命名规则:

  • 错误变量:以 Err 开头。它们通常是公开的,用于让调用者判断具体的错误类型。
  • 自定义错误类型:以 Error 结尾的结构体。

示例:

Go

1
2
3
4
5
6
7
8
9
10
11
12
// 一个预定义的错误变量
var ErrNotFound = errors.New("record not found")

// 一个自定义的错误类型
type SyntaxError struct {
Line int
Col int
}

func (e *SyntaxError) Error() string {
return fmt.Sprintf("syntax error at line %d, column %d", e.Line, e.Col)
}

8. 测试 (Test) 命名:保证代码质量的守护神

命名规则:

  • 测试函数:以 Test 开头,后面跟上你要测试的函数名,同样使用大驼峰。
  • 性能测试(基准测试):以 Benchmark 开头。

示例:

Go

1
2
3
4
5
6
7
8
9
// 这是对 AddUser 函数的测试
func TestAddUser(t *testing.T) {
// ... 测试逻辑
}

// 这是对 Sort 函数的性能测试
func BenchmarkSort(b *testing.B) {
// ... 性能测试逻辑
}

9. 项目目录结构:给你的项目一个家

一个清晰的目录结构能让项目井井有条。虽然没有强制规定,但社区形成了一些最佳实践:

  • cmd/:存放项目的主程序入口(main 函数就在这里)。
  • internal/:存放项目内部私有的代码,别的项目无法导入这里面的包,非常安全。
  • pkg/:存放可以被外部项目安全引用的公共代码库。
  • api/:存放 API 定义文件(比如 .proto 文件)。
  • configs/:存放配置文件。
  • scripts/:存放各种脚本(编译、部署、分析等)。

10. 注释 (Comments):代码的“使用说明书”

好的代码会说话,但有时也需要注释来补充说明。

注释规则:

  • 给每个公开的(导出的)东西写注释:每个公开的函数、方法、类型、常量都应该有一段简短的注释,解释它的用途。
  • 注释要以被注释的对象名开头
  • // 写单行注释,这是 Go 的首选。

示例:

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Package cache 提供了一个简单的内存缓存功能。
package cache

// MaxSize 是缓存可以存储的最大项目数。
const MaxSize = 100

// Cache 是一个线程安全的缓存结构体。
type Cache struct {
// ...
}

// Add 方法向缓存中添加一个键值对。
// 如果键已存在,它会覆盖旧的值。
func (c *Cache) Add(key string, value interface{}) {
// ...
}