这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
编程原则
简单性
- 消除“多余的复杂性”,以简单清晰的逻辑编写代码
- 不理解的到i吗无法修复改进
可读性
- 代码是写给人看的,而不是机器
- 编写维护代码的第一步是确保代码可读
生产力
- 团队整体工作效率非常重要
编码规范-代码格式
使用gofmt自动格式化代码
编码规范-注释
- 注释应该解释代码作用
// Open opens the named file for reading. If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// If there is an error, it will be of type *PathError.
func Open(name string) (*File, error) {
return OpenFile(name, O_RDONLY, 0)
}
- 注释应该解释代码如何编写
- 注释应该解释代码实现的原因
- 注释应该解释代码什么情况会出错
编码规范-命名规范
variable
- 简介胜于冗余
- 缩略词全大写,但当位于变量开头去不需要导出时,使用小写
- 变量距离其使用的地方越远,则需要携带更多的上下文信息
function
- 函数名不携带包名上下文信息,因为包名和函数名总是成对出现
- 函数名尽量简短
- 当名为foo的包某个函数返回类型Foo时,可以省略类型信息而不导致歧义
- 当名为foo的包某个函数返回类型T(T并不是Foo)时,可以在函数名中加入类型信息
package
- 由小写字母组成
- 简短并包含一定的上下文信息
- 不予标准库同名
编码规范-流程控制
- 避免嵌套,保持正常清晰逻辑
- 尽量保持正常代码路径为最小缩进
性能调优原则
- 要依靠数据不是猜测
- 要定位最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
性能分析工具pprof
import (
"log"
"net/http"
_ "net/http/pprof" // 自动注册 pprof 的 handler 到 http server
"os"
"runtime"
"time"
)
func main() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
log.SetOutput(os.Stdout)
runtime.GOMAXPROCS(1) //限制CPU使用数
runtime.SetMutexProfileFraction(1) //开启锁调用跟踪
runtime.SetBlockProfileRate(1) //开启阻塞调用跟踪
go func() {
//启动http server
if err := http.ListenAndServe(":6060", nil); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
业务服务优化
- 服务:能单独部署,承载一定功能的程序
- 依赖:Service A的功能实现依赖,Service B的响应结果,称为Service A依赖Service B
- 调用链路:能支持一个接口请求的相关服务集合及其相互之间的依赖关系
- 基础库:公共的工具包、中间件
流程
- 建立服务性能评估手段
- 分析性能数据,定位性能瓶颈
- 重点优化项改造
- 优化效果验证
建立服务性能评估手段
服务性能评估方式
- 单独benchmark无法满足复杂逻辑分析
- 不同负载情况下性能表现差异
请求流量构造
- 不同请求参数覆盖逻辑不同
- 线上真实流量情况
压测范围
- 单机器压测
- 集群压测
性能数据采集
- 单极性能数据
- 集群性能数据