Golang 的 slice、map、channe

Golang 的 slice、map、channel

    • slice
      • slice扩容策略
        • slice扩容策略
    • Map
    • Channel

slice

切片本身并不是动态数组或者数组指针。它内部实现的数据结构通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内。切片本身是一个只读对象,其工作机制类似数组指针的一种封装

  • 底层结构:array指针、长度、容量
  • 与 array 的区别
  • array 需要指定长度,且不可改变
  • Golang 所有的参数传递都是值传递
  • append 三种方式对比
  • 初始化时不指定长度、容量,直接 append 最慢,造成多次扩容;
  • 初始化时指定容量,不指定长度时 append 较快。适用于长度不确定但最大长度确定的情况;
  • 初始化时指定长度和容量,利用 index 赋值最快。适用于长度确定的情况。
  • 函数参数的传递是值传递
  • 切片的 array 字段存的是指针。如果没有发生扩容,修改在原来的内存中
  • 如果发生了扩容,修改会在新的内存中

slice扩容策略

slice扩容策略

###slice扩容策略
slice扩容策略:
首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)
否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap)
否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的 1/4(1.25倍),即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)

  • 使用 []Type{} 或 make([]Type) 初始化后,slice 不为 nil
  • 使用 var s []Type 后,slice 为 nil

Map

  • 实现是拉链法
  • map 实际上的值是个指针,传递的是指针
  • 修改会影响整个 map
  • map 的 key 和 value 都无法取地址,因为随着扩容地址会改变
  • map 存的是值,会发生 copy
  • map 删除 key 不会自动缩容

Channel

  • channel 是有锁的
  • channel 调用会触发调度
  • 高并发、高性能编程不适合使用 channel(锁降低了性能)
  • buffered channel 会发生两次 copy:
  • send goroutine -> buf
  • buf -> receive goroutine
  • unbuffered channel 会发生一次 copy:
  • send goroutine -> receive goroutine
  • unbuffered channel,receive 完成后 send 才会返回(阻塞发送)
  • for + select closed channel 会造成死循环,会给channel类型的0值
  • break 无法跳出 for,只能跳出 select

你可能感兴趣的:(golang)