引言

对标识符的命名向来是程序员们苦恼的事,这篇文章将参考标准库和一些流行轮子的命名规范来总结一下标识符的命名。

基本准则

  • 标识符命名由 Unicode 字母或下划线 _ 开头,后面跟一定数量的 Unicode 字母或 Unicode 数字或 下划线 _

  • 标识符命名不能由数字开头

  • 其他命名可能合法,如使用中文字符为标识符,这是合法的,但并不建议这么用

  • 大写和小写是不同的标识符

  • 大写字母开头的标识符是 public 的,而小写字母开头的标识符是 private 的

  • 关键字不能作为标识符

  • 可以使用预定义字符名,但是一般不建议使用

  • 空白标识符 _ 是一个特殊的标识符,仅用于占位

// 合法的标识符
_a
code_0
Abc
abc

//两个不同的标识符 
mi 
mI

// public 和 private 标识符
person // private 标识符,只能在此包引用
Person //public 标识符,其他包可以引用

// 不合法的标识符, Unicode 数字开头
22
2SDf

// 不合法的标识符,含不合要求的字符
(SDf
a.b
#sdfo

// 关键字不能作为标识符
int
type

//合法的,但是不建议使用的
啊啊

// new 是预定义字符,但是可以作为标识符名
func new() {
}

项目名

原则

  • 全小写,可以加上数字表示版本
  • 单词间使用中划线-间隔,首尾不要使用中划线

实例

// 常用框架,全小写
gorm
gin
grpc
// 单词间使用中划线(-)间隔
go-spew
go-mssqldb
go-testdb
universal-translator
// 可以使用数字表示特殊意义
go-sqlite3
reflect2

目录名

原则

  • 与包名相同

  • 尽量一个单词,或一个单词加缩写

  • 全小写,不使用下划线 _ 或中划线 -

  • 尽量不要与标准库重名

实例

// 标准库
archive
bufio
cmd

// gin 框架目录
binding
examples
internal
render

// 标准库有 database,就不要重名了
db

文件名

原则

  • 全小写字母,可以加数字表示特殊意义
  • 用下划线_ 隔离单词,但是尽量少用

实例

// 标准库 archive/tar 包
//全小写
common.go
strconv.go

// 下划线分割单词
example_test.go  // _.test.go 是测试文件
stat_unix.go

包名

原则

  • 与目录名相同

Tips:

为什么包名要与目录名相同:

  1. 导包时导入的是目录名

  2. 一个目录下都是一个包

  3. 具体可以看这篇文章

  • 全小写
  • 不使用下划线或中划线风格单词
  • 尽量不要与标准库重名
  • 包内的类型和函数不用加说明在哪个包

实例

// 标准库
log
time
http
rpc
// 流行轮子
gin
gorm

// 不要与标准库或轮子重名
mysql -> mys 
redis -> red

常量名

原则

  • 使用驼峰命名法(camelcase)
  • 不使用下划线
  • 首字母大小为 public,小写为 private
  • 将常量按类型分类
  • 公有常量放在私有常量前

实例

// 标准库 builtin 包,单个单词,小写
const (
	true  = 0 == 0 
	false = 0 != 0 
)

// 标准库 io 包,多个单词使用驼峰分割
const (
	SeekStart   = 0 
	SeekCurrent = 1 
	SeekEnd     = 2 
)

// go-sql-driver/mysql 库 const.go 文件
const (
	iOK           byte = 0x00
	iAuthMoreData byte = 0x01
	iLocalInFile  byte = 0xfb
	iEOF          byte = 0xfe
	iERR          byte = 0xff
)
const (
	defaultAuthPlugin       = "mysql_native_password"
	defaultMaxAllowedPacket = 4 << 20 // 4 MiB
	minProtocolVersion      = 10
	maxPacketSize           = 1<<24 - 1
	timeFormat              = "2006-01-02 15:04:05.999999"
)

//

接口名

原则

  • 使用驼峰命名法(camelcase)
  • 不使用下划线
  • 首字母大小为 public,小写为 private
  • 单个函数的接口以 er 结尾

实例

// 标准库 io 包 io.go 文件
//  单函数接口以 er 结尾
type Reader interface {
	Read(p []byte) (n int, err error)
}
// 驼峰命名
type ReadWriter interface {
	Reader
	Writer
}

// redigo 包 redis.go 文件
type Scanner interface {
    RedisScan(src interface{}) error
}

type Conn interface {

	Close() error

	Err() error

	Do(commandName string, args ...interface{}) (reply interface{}, err error)

	Send(commandName string, args ...interface{}) error

	Flush() error

	Receive() (reply interface{}, err error)
}

结构体名

原则

  • 使用驼峰命名法(camelcase)
  • 不使用下划线
  • 首字母大小为 public,小写为 private
  • 结构体成员名和结构体名原则相同
  • 为名词

实例

// sync 包 waitGroup.go 文件
// 驼峰命名
type WaitGroup struct {
	// 成员也是驼峰命名
	noCopy noCopy
	state1 [3]uint32
}

参数名

原则

  • 使用驼峰命名法(camelcase)
  • 首字母小写
  • 尽可能短,尽量为参数类型的首字母,或一个单词

实例

// fmt 包
//首小写,短
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
}

// 驼峰
func (p *pp) fmtBytes(v []byte, verb rune, typeString string) {
}

返回值名

原则

  • 使用驼峰命名法(camelcase)
  • 首字母小写
  • 尽可能短,尽量为参数类型的首字母,或一个单词
  • 尽量不使用命名参数

实例

// bufio 包
// 首字母小写,短
func (b *Reader) Discard(n int) (discarded int, err error) {
}

Receiver 名

原则

  • 尽量几个字母或一个字母
  • 小写
  • 尽量为类型的首字母

实例

// bufio 包
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
}

函数名

原则

  • 使用驼峰命名法(camelcase)
  • 不使用下划线
  • 首字母大小为 public,小写为 private
  • 表功能的尽量使用动词
  • 表判断的尽量使用 Is/Have 等前缀
  • 使用 construtor,在 type前加 new
  • getter 直接为变量名
  • setter 在变量前加 set

实例

//log 包
// 驼峰,动词,public
func Fatalln(v ...interface{}) {}
// filepath 包
// Is 前缀
func IsAbs(path string) bool {}

//construtor
type person struct {
}

func newPerson() *person {
	return &person{}
}

// getter
type person struct {
	name string
}

func (p *person) Name() string {
	return p.name
}

//setter
type person struct {
	name string
}

func (p *person) SetName(name string) {
	p.name = name
}

变量名

原则

  • 使用驼峰命名法(camelcase)
  • 不使用下划线
  • 首字母大小为 public,小写为 private
  • 遇到专有名词保持原样
  • 变量长度与作用域正相关
  • 循环变量使用单个字母

实例

// 专有名词
URLArray 或 urlArray 非 UrlArray

// gin 包
// 全句变量,长
var (
	default404Body   = []byte("404 page not found")
	default405Body   = []byte("405 method not allowed")
	defaultAppEngine bool
)

// 局部变量,短
c := engine.pool.Get().(*Context)

// 驼峰
rPath := req.URL.Path

//循环变量
for i := range "hah"{
}