这是我参与「第五届青训营 」伴学笔记创作活动的第 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
}
}