Golang的slice、map、channel使用的注意点

372 阅读2分钟

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

arrayslice
需要设置长度,长度为常量且不可改变长度可以改变
长度为类型的组成部分,[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是有锁还是无锁? 有锁

image.png

image.png

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 循环