整体上需要遵循:清晰,简约,简洁,可维护性,一致性
我们将在下列例子中体现上面原则,帮助大家理解这些抽象原则
1. 包名称 package
我们希望使用纯小写字母去建立包名称,这时候可能有同学要问,如果这个功能隶属于某个功能下的功能不需要在功能后缀名,冲突怎么办?
- Java 写法
我们在 java 中很容易就想在命名后面加类别比如UserService
, 这个其实是毫无意义的后缀 - Golang 规范
我们可以直接 /service/user 我们直接通过路径定位,service,同时 user 又都是小写。
这体现了 golang 的清晰和简洁
2. 常、变量命名
- Java 写法:
我们在 Java 中通常使用下划线,全大写来定义常量,使用小驼峰定义变量,首单词使用大写。 - Golang 规范:
我们在 golang 中同样使用驼峰进行命名,不过权限使用首字母大写来控制函数、变量是否对外部开放,在 golang 中拒绝使用不通用的缩写,通用缩写如‘api’,使用全大写命名API
在 golang 中 变量命名长度通常和使用范围成正比,比如简单一个计数变量仅仅5行内使用,使用
count
即可,反之,如果使用更大范围的计算器,接口流量计数器,可能就需要更长的命名,如interfaceTrafficCount
,可以避免冲突和歧义。
这体现了 golang 的清晰和简约
3. 导包分组
导入的包最好分为两组,一组为标准库
,一组为项目(其他)包
这体现了 golang 的清晰和简约、可维护性
4. 下划线导包
这个功能只建议导入初始化包的方法,因为这种导入是不可知的,维护性差的,不过下划线导包会默认执行
init()
前缀的方法,主要用于一些不需要明示的初始化操作。
package main
import (
_ "fmt" // 副作用导入,仅触发 fmt 包的初始化过程
)
func main() {
// 这里不会直接使用 fmt 包,但 fmt 包的 init() 函数会被执行
}
像 spring 的初始化过程,包括一些核心的对象,引用的创建是不需要对外展示的,因为并不能帮助维护者理解代码,只会增加系统的复杂性。
像 . 别名导入功能,在google 推荐规范中就直接不建议使用了,没有特例
这体现了 golang 的清晰和可维护性
5. 错误处理
由于 golang 中 ,处理处理错误更为灵活,我们可以对总是成功的错误函数,不去处理错误,但是绝大多数情况,golang 还是建议去处理错误或者把错误返回给上一级。
错误字符串通常开头小写,而日志记录通常首字母大写
这体现了 golang 的简约和可维护性
6. 字面格式化
对于在当前包之外定义的类型,结构体字面量通常应该指定字段名
// Good:
good := otherpkg.Type{A: 42}
如果能使代码更清晰,还是应该使用字段名,而且这样做是很常见的。例如,一个有大量字段的结构几乎都应该用字段名来初始化。
// Good:
okay := StructWithLotsOfFields{
field1: 1,
field2: "two",
field3: 3.14,
field4: true,
}
这体现了 golang 的简约、清晰和可维护性
7. if,for 的判断式不应该换行
// Good:
inTransaction := db.CurrentStatusIs(db.InTransaction)
keysMatch := db.ValuesEqual(db.TransactionKey(), row.Key())
if inTransaction && keysMatch {
return db.Error(db.TransactionError, "query failed: row (%v): key does not match transaction key", row)
}
// Good:
for i, max := 0, collection.Size(); i < max && !collection.HasPendingWriters(); i++ {
// ...
}
即使你的布尔判断式较长,也不建议换行,换行不能增加代码的美观性,且会增加阅读障碍。
这体现了 golang 的清晰和可维护性
8. switch 的 break 优化
// Good:
switch x {
case "A", "B":
buf.WriteString(x)
case "C":
// handled outside of the switch statement
default:
return fmt.Errorf("unknown value: %q", x)
}
// Bad:
switch x {
case "A", "B":
buf.WriteString(x)
break // this break is redundant
case "C":
break // this break is redundant
default:
return fmt.Errorf("unknown value: %q", x)
}
其实刚学 Java 的时候 就感觉 case 是有点不好用的,有点反直觉,明明已经case 到值了,为什么还要向下进行, go
的字句会自动中断,说人话就是默认每个case后加了一个break,不需要我们手动加了
这体现了 golang 的清晰
主要是对 c 和 go 不明晰语意的优化