GO语言通道及性能优化 | 青训营笔记

62 阅读3分钟

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

Go中的通道

并行&并发

并发:多线程程序在一个核上运行

并行:多线程程序在多个核的CPU上运行

在Go语言中,线程用户态,轻量级线程,线程是MB级别,协程:内核态,一个线程可以跑多个协程,栈是KB级别的

Channel

通道是什么,通道就是goroutine之间的通道。它可以让goroutine之间相互通信 一共有三种类型的定义,可选的<-代表channel的方向。如果没有指定方向,那么Channel就是双向的,既可以接收数据,也可以发送数据。

chan T          // 可以接收和发送类型为 T 的数据
chan<- float64  // 只可以用来发送 float64 类型的数据
<-chan int      // 只可以用来接收 int 类型的数据

使用make初始化来创建,可以初始化设置容量,代表通道容纳的最多的元素的数量,缓存的大小

make(chan int, 100)

Channel通道在使用的时候,有以下几个注意点:

  • 1.用于goroutine,传递消息的。
  • 2.通道,每个都有相关联的数据类型,nil chan,不能使用,类似于nil map,不能直接存储键值对
  • 3.使用通道传递数据:<- chan <- data,发送数据到通道。向通道中写数据 data <- chan,从通道中获取数据。从通道中读数据
  • 4.阻塞: 发送数据:chan <- data,阻塞的,直到另一条goroutine,读取数据来解除阻塞 读取数据:data <- chan,也是阻塞的。直到另一条goroutine,写出数据解除阻塞。
  • 5.本身channel就是同步的,意味着同一时间,只能有一条goroutine来操作。

最后:通道是goroutine之间的连接,所以通道的发送和接收必须处在不同的goroutine中。

Go中的语言编码规范及性能调优

编码的核心目标是降低阅读代码的成本,重点考虑上下文信息,设计间接清晰的名称。

注释规范

  • 注释可以帮我们很好的完成文档的工作,写得好的注释可以方便我们以后的维护。
  • /**/ 的块注释和 // 的单行注释两种注释风格, 在我们的项目中为了风格的统一,全部使用单行注释,注释的质量决定了生成的文档的质量。
  • 注释应该解释代码实现的原因,提供代码不能提额外的上下文
  • 注释应该解释代码什么情况会出错,解释代码的限制条件
  • 所有导出对象都需要注释说明其用途;非导出对象根据情况进行注释。

错误和异常处理

  • error 尽可能提供简明的上下文信息链,方便定位问题
  • panic 用于真正异常的情况
  • recover 生效范围,在当前goroutine的被defer的函数中生效

性能优化

性能的表现需要实际数据衡量,Go语言提供了基准性的测试

  • 性能优化的前提是满足正确可靠、间接清晰等质量因素
  • 性能优化是综合评估,有时候时间效率和空间效率可能对立
  • 针对Go语言特征,介绍Go相关的性能优化建议

slice预分配内存,尽可能在使用make()初始化切片时提供容量信息

性能优化建议-Map

  • 不断向map中添加元素的操作会触发map的扩容
  • 提前分配好空间可以减少内存拷贝和Rehash的消耗
  • 建议根据实际需求提前预估好需要的空间
func NoPreAlloc(size int){
    data := make(map[int]int)
    for i := 0; i < size; i++{
        data[i] = 1
    }
}

func NoPreAlloc(size int){
    data := make(map[int]int, size)
    for i := 0; i < size; i++{
        data[i] = 1
    }
}