Go 语言要点备忘(上)
序
- 2009 年 11 月 10 日正式开源,这一天被确定为 Go 语言的诞生日;
- 吉祥物是 Rob Pike 的夫人 Renee French 设计的地鼠;
- 程序员被称为 Gopher
- 2018 年 8月 19 日,Go 1.5 发布。这是具有里程碑意义的版本。从这个版本开始,Go 实现了自举 ;
- 设计哲学是 组合
- Go 1.16 版本,Go module 成为默认的依赖包管理和构建机制;
最小的标准布局:
1 | - go.mod |
或者
1 | - go.mod |
常见的其他目录:
cmd
: 存放项目要构建的可执行文件对应的main
包的源文件;pkg
: 存放项目自身要使用并且同样也是可执行文件对应main
包要依赖的库文件;internal
: 对于不想暴露给外部引用,仅限内部使用的包;
命名
- 包:小写单个单词命名
- 包名可以不唯一,但每个包的导入路径唯一
- 如果缩略词首字母大写,其他字母也要大写,比如
HTTP
、URL
,而不是使用Http
、Url
- 同样,使用
ID
而不要用Id
- 同样,使用
- 常量的命名并不要求大写,比如:
1 | const ( |
注释
- 支持 C 风格的块注释
/* */
,也支持 C++ 风格的行注释//
; - 块注释主要用于包的注释;
- 应该使用完整的句子,即使看起来有一些冗余;
- 包注释是不应该有空白行;
环境
- 无论你是否使用默认的安装位置,最好显式定义
GOPATH
语言基础
- Go 会对未初始的变量赋零值
- 当需要初始化一个变量为零值时,使用
var x int
这种形式,可以清晰地表达零值的意图 - Go 中很少使用数组,更多使用切片
- 如果可以预估出底层数组所需的数量,强烈建议带上
cap
参数 - 切片在 Go 中表示为
(*T, len, cap)
,其中*T
指向切片对应的底层数组指针,len
是切片当前长度,cap
是切片的容量
- 如果可以预估出底层数组所需的数量,强烈建议带上
- 使用数组字面量,可以不定义具体长度,而使用
...
,比如var x = [...]int{10, 20, 30}
- 为了避免复杂的切片行为,不要对子切片使用
append
byte
是uint8
的别名;rune
是int32
的别名- Go 不允许自动的类型转换,如果类型不一致,需要显式进行转换
- 做了预初始化的
strings.Builder
连接构建字符串效率最高
函数
- Go 语言是一种值传递的语言。这意味着提供变量给一个函数作为参数时,Go 总是复制该变量的值;
context
一般要作为函数的第一个参数;
类型、方法和接口
- 区分使用指针接收者(receiver)还是值接收者:
- 如果方法修改了接收者,那么必须使用指针接收者
- 如果方法需要处理
nil
实例,那么必须使用指针接收者 - 如果方法不修改接收者的值,可以使用值接收者
- 不要把 Context 加入到结构体类型,你应该传入到类型方法。
Context
是不可变的,所以最好在多个调用中传递相同的ctx
;- 接口通常应该属于使用接口类型的包,而不是实现接口类型的包。接口类型的具体实现应该返回具体的类型(通常是指针或者结构)类型。这样可以将新的方法加入到实现中而不需要大量重构
- 也就是「接收接口,返回具体类型」
- 接口应该是可以使用真实实现的,而不是为
mocking
服务的 - 不要在接口使用之前定义它(保持最小接口)
1 | package producter |
应该返回具体的类型:
1 | package producter |
错误处理
- 返回一个类型为
error
的值作为函数的最后一个返回值来返回错误 - 不要使用
panic
作为正常情况下的错误处理; - 错误字符串信息应该 小写开头 。
- 不要使用
_
抛弃错误。如果函数返回一个error
,应该检查来确保函数成功;- 处理这个
error
,或者return
,或者真的是特殊情况下panic
- 处理这个
不要这样写:
1 | if err != nil { |
而是这样写:
1 | if err != nil { |
模块、包和导入
- Go 的库管理依赖于三个仓库:仓库、模块和包
- 项目的源代码通过版本控制系统存储在仓库之中
- 模块是 Go 库或者应用程序的根目录
- 模块中包含一个或者多个包,用来组织模块的结构
- 尽量避免
init
函数init
函数没有输入和输出,那么只能作为副作用使用- 可以在同一个包中定义多个
init
函数,但是顺序难以确定
- 如果只是需要一个包的副作用,例如:
import _ "pkg"
,那么应该只在main
或者测试中导入 - 只在测试出现循环依赖的时候,使用
.
导入包,否则程序会难以阅读
单元测试
- 所有测试文件名都是以
_test.go
结尾 - 测试函数都是以
Test
开头,并都接受一个类型为*testing.T
的参数 - 通常约定是使用
Test
加上被测试函数的名字
Go 工具链
gofmt
:应该自动用gofmt
格式化代码;goimports
:gofmt
超集,会自动删除不必要的导入;
godoc
:提取代码文档;
参考资料
- Gopher 必读的 Effective Go
- Effective Go 补充,Go Code Review Comments
小结
Go 基础概念还是比较简单的,本文并不面面俱到,而且也不是从 0 开始,Go 还有很多细节值得展开,但是时间有限,就没有写了。
(TODO…)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小谷的编程随笔空间!
评论