slice
a := make([]int, 100) // slice
a := [100]int{} // array
slice是go语言独有的一种数据结构,它不像在java语言中可以直接定义一个arraylist底层直接指向一个数组
slice是如何实现的?和array有什么关系呢? 下面的就是slice的结构体定义
type slice struct {
array unsafe.Pointer
len int
cap int
}
其中有三个属性
- array:一片内存地址指针
- len:长度
- cap:容量
cap的扩容机制:
当cap < 1024 每次*2
当cap >= 1024 每次*1.25
扩容的时候会重新分配array的内存(在func内对slice的修改可能会让外部的slice中值失效)
性能
- 预先分配内存可以提升性能
- 直接使用 index 赋值而非 append 可以提升性能
vs array
| array | slice |
|---|---|
| 需要设置长度,长度为常量且不可改变 | 长度可以改变 |
| 长度为类型的组成部分,[100]int{}和[101]int{}不是相同的类型 | 类型设置的常量无关 |
| 作为参数的时候会产生cpoy动作 |
map
mapV := make(map[string]string) //make map会产生一个指针,mapV就是这个指针的地址
map的key和value都是不可取地址的,它们的地址会随着map的扩容而发生改变
map在删除key的时候是不会自动缩容的
深度解析go map qcrao.com/post/dive-i…
channel
channel是有锁还是无锁? 有锁
recvq: 从这里找到goroutine进行信息的发送
channel的调用会触发调度,高并发、高性能编程不适合使用channnel
创建方式
make(chan Type) // 无缓冲区
make(chan Type,len) //有缓冲区
有无缓冲区的差别
- 无缓冲区
- 只发生一次 copy: send goroutine -> receive goroutine
- 并且保证了 receive 完成后 send 才返回
- 有缓冲区
- 发生两次 copy : send goroutine -> buf ->receive goroutine
坑点
- for+select closed channel 会造成死循环
- select 中进行 break 无法跳出外边的 for 循环