Day 3 Go | 青训营笔记

64 阅读4分钟

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

高质量代码:

  1. 正确性: 是否考虑各种边界条件,错误的调用是否能够处理
  2. 可靠性: 异常情况或者错误的处理策略是否明确,依赖的服务出现异常是否能够处理
  3. 简洁: 逻辑是否简单,后续调整功能或新增功能是否能够快速支持
  4. 清晰: 其他人在阅读理解代码的时候是否能清楚明白,重构或者修改功能是否不会担心出现无法预料的问题

编程原则:

  1. 简单性消除“多余的复杂性”
  2. 可读性代码是给团队成员和自己看的,想要易维护的代码,第一步就是确保代码可读
  3. 生产力提高团队的工作效率

编码规范:

1. 代码格式
可以使用go fmt,进行代码的格式化。Go imports,对依赖包进行管理
2. 注释
解释代码的作用,如何实现,实现原因,可能会出的错误,尽量不要出现代码和注释不相关的内容,也容易造成误导,

尤其是在编写包的时候,公共符号都需要添加注释,无论长度和复杂度如何,库中的函数都要进行注释 既不明显,也不简短的公共功能,也需要注释

命名规范

变量命名

  1. 变量命名缩略词要大写、驼峰式命名
  2. 变量距离被使用的地方越远,需要携带更多的上下文信息,以便于在不同地方能够轻易识别出含义 函数命名 不携带包名的上下文信息,尽可能简短。

包命名 只由小写字母组成,不包含大写字母和下划线,主要与标准库同名
命名规范也可以参照标准库

控制流程

尽量少使用嵌套,尤其对于错误处理,会导致代码阅读难度增加,如图所示:(代码来自字节内部课)

// Bad
func OneFunc() error {
    err := doSomething()
    if err == nil {
        err := doAnotherThing()
        if err == nil {
            return nil // normal case
        }
        return err
    }
    return err
}
//Good
func OneFunc() error {
    if err := doSomething();err != nil {
        return err
    }
    if err := doAnotherThing(); err != nil {
        return err
    }
    return nil // normal case
}

错误和异常处理

可以使用错误跟踪链就是一个error,嵌套另一个error

考虑到错误链可能会很多,可以使用errors.is来判断错误链上的所有错误是否包含特定的错误,如图所示:

使用errors.as可以获取错误链上特定种类的错误。 如图所示:(代码来自字节内部课)

data ,err = lockedfile.Read( targ )
    if errors.Is(err, fs.ErrNotExist) (
    // Treat non-existent as empty, to bootstrap the "latest" file
    // the first time we connect to a given database.
    return []bytef{}, nil
}
return data, err

不要在业务代码中使用panic
调用的函数中不包含recover会造成程序崩溃
当程序启动阶段发生不可逆转的错误时,可以在init或者是main函数中使用panic

何时使用recover 当我们引用一些包或者是一些标准库的之后,运行程序会出现panic。在运行阶段,不想让这个panic影响我们的逻辑,可以调用recover(),只能在 defer 中使用。

注意:嵌套无法生效。只能在当前的goroutine内生效。在recover之后也可以把错误打印出来

性能优化

建议
Slice切片预分配内存,尽可能的预测需要分配的空间 以避免内存不够,发生拷贝。
map类似

字符串处理
有三种:

  1. 直接用加号
  2. 使用springs builder
  3. bytebuffer Strength builder的性能是最好的,直接用加号性能最差。

字符串在go语言中是不可变类型,占用内存大小是固定的,所以每次使用加号都会重新分配内存
而另外两种形式,底层都是[ ]byte数组,会扩容,但不会重新分配

空间优化

可以使用空结构体来充当占位符。但是不会占用内存,尤其是对于实现set类型,可以用map进行底层实现,只使用key,Value利用空结构体

使用atomic包,来实现多线程编程,或者利用加锁
但是锁的实现是通过操作系统来实现,属于系统调用,Atomic操作是通过硬件实现效率要比锁高

在满足正确可靠,简洁清晰的质量的前提下,进行程序性能的提高。不能一味的追求程序的性能

性能调优实例

调优原则:

  1. 依靠数据而不是盲目猜测
  2. 定位最大的问题,而不是细枝末节
  3. 不要过早优化,也不要过度优化

性能分析工具pprof

希望知道应用在什么地方耗费了多少 CPU、Memorypprof 是用于可视化和分析性能分析数据的工具
net/http/pprof包的init函数中注册了以下路由到http服务中,用浏览器打开(http://localhost:8080/debug/pprof/)

即可使用pprof提供的功能。

测试程序github地址

功能简介
如图所示(来自字节内部课)

image.png

引用

pprof使用的图文说明