这是我参与「第五届青训营」伴学笔记创作活动的第 3 天
一、高质编程与规范
1.1简介
- 简单性:消除多余复杂性
- 可读性:确保代码可读
- 生产力:团队工作的效率
1.2 编码规范
- 代码格式
- 注释
- 命名规范
- 控制流程
- 错误和异常处理
1.2.1代码格式
gofmt 能自动化 党建IDE都支持方便的配置
goimports 等于gofmt加上依赖包管理 自动增删依赖的包引用、将依赖包按字母序排列并分类
1.2.2注释
- 作用
- 如何做的
- 实现的原因
- 什么情况会出错
注释应该提供代码为表达出的上下文信息
1.2.3命名规范
- 简洁
- 缩写词全部大写
- 全局变量在名字中需要更多的信息
- 降低阅读代码成本
1.2.4流程控制
- 避免嵌套
1.2.5错误和异常处理
- 使用
errors.New来创建匿名变量来直接标志简单错误 - 如果有格式化需求,使用
fmt.Errorf可以用%w在关联错误 - 在错误链上获取特定种类错误,使用
errors.As
1.2.5.1 panic
- 调用函数不包括recover会造成程序崩溃
- 建议使用
error替代panic
1.2.5.2 recover
- 只能在defer中使用
- 嵌套无法使用
- 只在当前goroutine生效
- 语句是后进先出
小结
error尽可能提供简明的上下文信息链,方便定位问题panic用于真正异常的情况recover生效范围,在当前goroutine的被defer的函数中生效
性能优化
1.3.1性能优化Benchmark
go test -bench=. -benchmem测试性能
- 测试名
- 测试次数
- 花费时间
- 执行申请内存
- 每次执行申请次数
1.3.2 优化建议-Slice
预分配内存
type slice struct{
array unsafe.Pointer
len int
cap int
}
在已有切片基础上创建切片,可使用copy代替re-slice
1.3.3 Map
- 预分配内存
- 提前分配可以减少内存拷贝和Rehash
1.3.4字符串处理
使用strings.Builder 会缩短直接使用i++时间效率
在拼接时候:
+ < strings.Builder < bytes.Buffer < strings.Buffer
- 每次都会重新分配内存
func preStrBuilder(n int, str string)string{
var builder stings.builder
builder.Grow(n * len(str))
for i := 0; i < n; i++{
builder.WriteString(str)
}
return builder.String()
}
1.3.5空结构体
- struct{}不占用任何空间
- 可作为占位符号 1.节省资源 2.空结构本身具备很强的语义,不需要任何值 例:实现set 可以用map代替 只需要map的键不需要值
1.3.6 -atomic包
type atomicCounter struct{
i int 32
}
func AtomicAddOne(C
*atomicCounter){
AtomicAdd32(&c.i, i)
}
- 锁是通过系统实现,属于系统调用
- atomic是通过硬件实现,效率比锁高
- sync.Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量
- 对于非数值操作,可以使用atomic.Value,能承载一个interface{}