高质量及优化 l 青训营笔记

102 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 3 天

一、高质编程与规范

1.1简介

  1. 简单性:消除多余复杂性
  2. 可读性:确保代码可读
  3. 生产力:团队工作的效率

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. 测试名
  2. 测试次数
  3. 花费时间
  4. 执行申请内存
  5. 每次执行申请次数

1.3.2 优化建议-Slice

预分配内存

type slice struct{
	array unsafe.Pointer
	len int
	cap int
}

append.png

在已有切片基础上创建切片,可使用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{}

二、性能调优

2.1分析工具pprof

pptof.png