这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
高质量代码
编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码
- 各种边界条件是否考虑完备
- 异常情况处理,稳定性保证
- 逻辑简单,易读易维护
代码格式及格式化
Go 语言中使用官方提供的工具gofmt,能够自动格式化Go 语言代码为官方统一风格。
编码规范
注释
代码是写给人看的
公共函数及符号必须注释,例如open()函数,重名的太多了,所以需要写清楚你所写的open()实现了怎么的功能,但是对于isBoolean()函数其功能已经一目了然,就不需要注释了。
注释可以提供格外的上下文和有用信息,比如某个请求处理方法可以在注释中写明实际请求相关信息以供参考。
但是Go 语言的注释显然过于简陋,没有Javadoc类似的功能,注释能力显得力不从心,不宜长篇大论,可能这也是Go 语言主打简洁的特点。
命名
简洁胜于冗长
缩略词需要大写,但是如果位于变量开头,或者不对外开放或是导出,则全小写,例如ServiceHTTP和xmlHTTPRequest,前者对外,后者不对外。
变量距离其被使用的地方越远,则需要带越多的上下文信息,例如for循环中的索引变量i,由于其作用单一,作用范围狭小,完全没必要增加在命名中的注释信息。
性能调优
高级程序员必会
- 为
slice和map预分配内存(通过make指定容量信息)
这一点往期笔记也提到过,因为切片在扩容时会整体转移到新的地址,在此期间会占用大量性能进行内存分配。
//没有预分配,扩容时低效
func NoPreAlloc(size int) {
data:= make(map[int]int)
for i:= 0; i < size; i++ {
data[i] = 1
}
}
//预分配空间,优化性能
func NoPreAlloc(size int) {
data:= make(map[int]int, size)
for i:= 0; i < size; i++ {
data[i] = 1
}
}
- 不要使用
+拼接字符串
拼接字符串时,用strings.Builder比直接使用+或使用bytes.Buffer更快,其中使用+至少比另外两种方式慢了2~3个数量级,因为+在拼接字符串时会不断去进行扩容,产生大量内存分配从而占据大量资源。
//用于加号拼接字符串,极其低效
func Plus(n int, str string) string {
s:= ""
for i:= 0; i < n; i++ {
s+= str
}
return s
}
//使用strings.Builder优化性能
func Plus(n int, str string) string {
var builder string.Builder
for i:= 0; i < n; i++ {
builder.WriteString(str)
}
return builder.String()
}
- 使用
copy代替re-slice避免内存泄漏
在原有切片上创建切片时,并不会产生新的数组,从而占用原有数组,这可能会引起内存泄漏的问题(即原有切片占用的更大的内存没有得到释放),此时先创建一个新的切片并使用copy可解决该问题。
- 使用空结构体
struct{}占位减少内存消耗 - 使用
atomic包加锁提高时间性能
在Go 中atomic的操作范围是硬件层的,速度高于sync一个数量级,但是sync保护的不仅是数据,而是一段逻辑,应该视情况选择使用。
今天的学习内容非常实用,从编码规范到注释规范以及性能调优,都对未来从事任何语言的开发工作都大有裨益,之后也会细细研究其中的智慧。