golang slice map分析

Golang 容器

Slice 切片

截取

双索引切片

slice := data[low:high]

含义

len = high - low
cap = cap(data) - low

三索引切片

对于max参数:当你需要限制 slice 的 capacity,防止 append 修改原数组时使用

slice := data[low:high:max]

含义

len(slice) = high - low
cap(slice) = max - low

无论是双索引 slice 还是三索引 slice,只要 appendlen + 新元素 <= cap,就会在原底层数组上写;如果 len + 新元素 > cap,Go 就会分配新的底层数组。

示例

package  main

import  "fmt"

func main() {
    slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    s1 := slice[2:5]
    s2 := s1[2:6:7]
    s2 =  append(s2, 100)
    s2 =  append(s2, 200)
    s1[2] =20
    fmt.Println(s1)
    fmt.Println(s2)
    fmt.Println(slice)
}
slice = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

//基于slice向后总共截取3个,实际cap 占据从9-2=7个空间
s1= slice[2:5] = [2, 3, 4]   //和slice共用底层数组 len=3 cap= 8

//index=2开始 等于s1[2],等于slice[4],基于slice向后总共截取4个
//由于max=7,因此实际cap占据7-2 = 5个空间
s2 := s1[2:6:7]= [4,5,6,7] //和slice共用底层数组 len=4 cap= 5

//由于s2 有多余的空间,所以基于原数组添加100,此时len=5 cap=5
//slice = [0, 1, 2, 3, 4, 5, 6, 7, 100, 9]
s2 =  append(s2, 100)

//由于s2 没有多余空间,所以基于原数组扩容创建新数组
//slice = [0, 1, 2, 3, 4, 5, 6, 7, 100, 9]
//s2 = [4, 5, 6, 7, 100, 200]
s2 =  append(s2, 200)

//s1还是基于元素组  [0, 1, 2, 3, 20, 5, 6, 7, 100, 9]
//s1 = [2, 3, 20]
 s1[2] =20

扩容规则

  • 原来的 slice 容量 oldcap 小于 1024 的时候
    • slice 的容量 newcap 的确是 oldcap 的 2 倍。
  • oldcap 大于等于 1024 的时候
    • 每次增加 1.25 倍 (后续版本优化后会内存对齐,大约是这个容量)

Map 散列表

创建 map

ageMp :=  make(map[string]int)
// 指定 map 长度
ageMp :=  make(map[string]int, 8)
// ageMp 为 nil,不能向其添加元素,会直接panic
var ageMp map[string]int