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,只要
append后len + 新元素 <= 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