这是我参与「第六届青训营」伴学笔记创作活动的第 3 天
Go高质量编程
简介
首先介绍一下高质量:顾名思义质量很高,所以编写的代码能够达到正确可靠(尽可能的不出错误),简洁清晰(自己和别人都可以快速清楚的理解)的目标可称之为高质量代码。其次,go语言开发者普遍认为的编程原则:简单性 可读性 生产力
编码规范
代码格式
一定使用gofmt进行格式化,另一种是goimports也是go语言官方提供的工具,它实际上等于gofmt加上依赖包管理拥有自动增删以来的包引用,将依赖包按字母序排序并分类的功能。
注释
注释是很有必要的,应该从下面几个方面进行注释
- 解释代码的作用 (注释适合说明公共符号,函数功能简单而明显可以省略)
- 解释代码的实现 ( 对代码中复杂、隐晦的逻辑进行说明)
- 解释代码实现的原因 (解释代码的外部因素,使人可以理解脱离了上下文后的代码)
- 解释代码可能出错的情况 (提醒使用者一些潜在的限制条件或者无法处理的情况)
- 公共符号的注释 (Google Style指南有两条规则:任何既不明显也不简短的公共功能必须予以注释;无论长度或者复杂度如何,库中的任何函数都必须予以注释。)一个例外是,不要注释实现接口的方法!
命名规范
变量
- 简洁胜于冗长
- 缩略词使用全大写(如HTTP,XML等),但当其位于变量开头且不需要导出时,使用全小写(如使用ServeHTTP而不是ServeHttp, 使用XMLHTTPRequest或者xmlHTTPRequest)
- 全局变量在名字中需要携带更多的上下文信息,使得不同地方都可以轻易辨认出其含义。
函数
- 函数名不包含包名的上下文信息,因为包和函数总是成对出现的。
- 尽量简短
- 当名为foo的包中某个函数的返回类型是Foo时,可以省略类型信息而不产生歧义,当返回的是其余类型时,则可以在函数名中加入类型信息。
包
-
只有小写字母组成。
-
简短并包含一定的上下文信息
-
不和标准库同名。
-
尽量满足以下规则:
- 不使用常用变量名作为包名
- 使用单数而不是复数
- 谨慎地使用缩写,利用使用
fmt在不破坏上下文的情况下比format更加简短。
性能优化
建议-Benchmark
使用Go语言提供的基准性能测试工具Benchmark
Slice
尽可能在使用make初始化切片时提供容量信息,减少内存分配次数。另一个是Slice可能会出现大内存未释放的情况(原切片较大,代码在原切片 基础上新建小切片。原底层数组在内存中有引用,得不到释放),解决的办法是可以使用copy替代re-slice重切片。
Map
类似Slice,尽可能地在make时为Map提供容量信息,减少内存拷贝和重哈希的消耗。
字符串处理
str += ...
var builder strings.Builder
builder.WriteString(str)
buf := new(bytes.Buffer)
buf.WriteString(str)
代码中展示了三种不同的字符串拼接操作,使用+的拼接性能最差,而Builder和Buffer相近,Buffer最快。由于字符串在go中是不可变类型,内存大小占用固定,因而使用+每次都会重新分配内存。而另外两个结构的底层都是[]byte数组,通过内存扩容策略不需要每次都要重新分配内存。
空结构体
使用空结构体可以节省内存,也可以作为占位符使用。
atomic
锁的实现是通过操作系统来实现,属于系统调用,而atomic操作时同硬件实现效率比锁高。另外,sync.Mutex应该用来保护一段逻辑,不仅限于变量。