Golang编程技巧和性能优化|青训营笔记

349 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记。

Golang编程技巧

编程的原则

  • 简单性:消除多余的复杂性,命名简单易懂
  • 可读性:代码加注释可以帮助他人快速理解代码
  • 生产力:统一代码风格,方便团队工作

1.编码规范之命名

  • 命名尽量简单,不要出现信息冗余。

2.编码规范之控制流程

  • 如果两个分支中都包含return语句,可以去除冗余的else。
if ok {
    return x
}else{
    return y
}


if ok {
    return x
}
return y

第一种代码在go的早期版本可能会报错,但现在已经修复了该bug。

  • 优先处理错误情况,减少代码嵌套,提高可读性。
err := doSomething()
if err == nil{
    err := doAnother(){
        ...
    }
}

if err := doSomething(); err != nil{return err}
if err := doAnother(); err != nil{return err }

2.编码规范之错误和异常处理

  • 一般情况出现简单的错误可以直接使用errors包中的New()函数来生成一个包含错误信息的error,并返回。
  • 对于复杂的错误,可以在fmt.Errorf中使用 %w关键字来嵌套错误。这样不会丢失原来的错误信息。
  • 在Go语言中,如果出现了panic则表示程序无法继续运行下去,一般需要谨慎使用。使用recover函数可以让程序即使发生了panic也可以正常退出。但是需要注意:(1)recover只能在defer函数中使用(2)只在当前goroutine生效(3)嵌套无法生效

3.性能优化之预分配内存

在Go语言中Slice是一个经常使用的数据结构,因此了解一些关于slice性能优化的技巧是必要的。

  • 使用Slice时,尽量使用make()初始化时提供容量信息,让内存一次性分配好,这样就可以避免以后添加元素后容量不够,需要重新扩容的问题。同样的,使用Map也应该尽可能地预分配内存。
  • 在已有切片的基础上创建切片,不会创建新的底层数组, 这会使得原来的底层数组在内存中有引用,无法释放。建议用copy 代替 reslice

4.字符串拼接

Go语言中的字符串拼接大概有四种方法。

  • 使用"+"操作符来拼接字符串
  • 使用fmt.Sprintf()
  • 使用strings.Join()
  • 使用bytes.Buffer
  • 使用strings.Builder

前三种操作的性能差别不大,后两种的性能也差别不大,可能经过优化后的strings.Builder更好一点,但是后两种操作在拼接大量字符串时性能远高于另外三种方法。

5.空结构体

空结构体 struct{}实例不占据任何的内存空间,可作为占位符使用,它可以节省资源。一个使用场景就是集合的实现,在Go语言中是没有集合这个数据结构的。我们可以用Map来实现类似的功能,因为Map的key是唯一的,这时我们其实是不需要Map的值的,因此可以用空结构体来占用。

此外也可以用Bit数组来实现集合。

6.atomic包

atomic操作是通过硬件实现的,效率比sync.Mutex的效率高。

锁的实现是通过操作系统来实现的,属于系统调用。

sync.Mutex应该用来保护一段逻辑,而不仅仅是一个变量。