课程笔记三 实现高质量编程的建议 | 青训营笔记

56 阅读4分钟

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

如何实现高质量编程呢,一方面是编写代码的高质量,一方面是性能高质量

加油加油加油!!!

高质量编程

高质量代码--正确可靠,简洁清晰的目标

  1. 边界条件
  2. 异常处理,稳定性保证
  3. 易读易维护,注意团队合作!!!

编写原则

  1. 简单性 简洁清晰的逻辑编写代码(复杂的难以修改与维护
  2. 可读性 代码是写给人看的!!!
  3. 生产力 即工作效率

注意

  • 代码格式
  • 注释
  • 命名规范
  • 控制流程
  • 错误与异常处理

注释

公告符号始终要进行注释,功能说明

注释主要是提供额外信息!!要有用

有一个完整的能提供信息的代码注释,无论是他人或者自己对于代码的使用都有很大帮助

  • 代码作用
  • 代码如何做(实现过程)
  • 实现的原因
  • 为什么会出错
  • 代码限制条件
  • 修改代码逻辑时要更新注释

推荐使用gofmt自动格式化代码

命名规范

变量命名

  • 简洁
  • 缩略词全大写,但位于开头且不需要导出时全小写
  • 全局变量时要带上自己的信息

函数命名

  • 不需携带包名的上下文信息,因为是成对出现的
  • 尽可能简短

包命名

  • 只小写字母
  • 不与标准库同名
  • 简短并包含一定的信息
  • 缩写的话需要不破环原意

命名规范与注释的核心目标是降低代码阅读理解的成本!

控制流程

  • 避免分支上的嵌套,去除不需要的else
  • 尽量避免多重缩进
  • 线性原理,逻辑尽量直线

错误和异常处理

  • 简单错误

error.New 创建匿名变量表示简单错误,格式化:fmt.Errorf

  • 复杂错误

WarpUnwarp (错误的嵌套,实现错误的跟踪链),在fmt.Errorf中使用%w关键字将错误关联到错误链中

list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles))
if err! != nil {
    return fmt.Errorf("reading srcfiles list: %w", err)
}
  • 错误判定

错误链上获取特定错误,使用errors.Is

if errors.Is(err, fs.ErrNotExist) {
    return []byte{}, nil
}

错误链上获取特定种类的错误,使用errors.As

if errors.As(err, &pathError){
    fmt.Println(err)
}
  • panic

不建议在业务代码中使用panic,

调用函数不包含recover 会造成程序崩溃,

问题可以被解决或者屏蔽时用error代替,

启动时发生不可逆错误时,可以在 init 或者 main 使用 panic

  • recover

recover 只能在被 defer 的函数中使用

嵌套无法生效

只能在当前 goroutine 生效

defer 语句后进先出

性能调优

  • 性能评估

首先,我们需要对我们的项目代码进行性能评估,Golang提供了相关的基准性能测试--benchmark工具

$ go test -bench=. -benchmem
$ go test -run=. -v

结果说明:

image.png

性能优化建议

  • 预分配 slice的初始化提供容量信息,防止多次内存分配(需要扩容)

  • 在已有切片上创建切片,不会释放原底层数组,占用空间。 可以创建新的切片,用copy进行引用

  • map预分配内存 初始化make一个容器大小,与slice的扩容同理

  • 字符串处理 字符串为不可变类型,每次使用+凭借都会重新分配内容,使用stings.Builder维护了一个[]byte数组,并转化成字符串返回。

同理,在预知大小的情况也可以进行预分配

image.png

  • 空结构体节省内存 因为空结构体不占用内存空间,可以用来占位 比如实现cet用map实现时,只需要键不需要值的时候

  • 多线程时的线程安全可使用atomic包(硬件调用),维护一个原子变量,对比加锁(系统调用)保护一个变量,时间性能更好,

加锁更适合用于保护一段逻辑

小结

从代码质量与性能优化的方向来讲高质量代码,个人认为代码的可读性、可靠性的优先级更高一点,在实现了代码可读性,安全性等条件之后再去追求高性能更好。