管道

切片

每个切片都指向一个底层数组

数据结构

1
2
3
4
5
6
// src/runtime/slice.go:slice
type slice struct {
array unsafe.Pointer
len int
cap int
}

操作

使用数组创建slice

使用数组创建slice时,slice将与原数组共用一部分内存。

扩容

扩容的本质:重新分配内存(len > cap时),拷贝数据,追加数据。

  1. cap < 1024, cap = 2 * cap
  2. cap > 1024, cap = 1.25 cap

Map

Go语言的map基于Hash表实现。

特性

初始化

1
2
3
4
5
6
7
8
9
10
// make初始化
func MapInitByMake() {
m := make(map[string]int, 100)
m["apple"] = 1
m["banana"] = 2

for k, v := range m {
fmt.Printf("%s-%d\n", k, v)
}
}

增删改查

1
2
3
4
5
6
7
8
9
10
func MapCRUD() {
m := make (map[string]string, 10)
m["apple"] = "red" // append
m["apple"] = "green" // alter
delete(m, "apple") // delete
v, exist := m["apple"] // query
if exist {
fmt.Printf("apple-%s\n", v)
}
}

删除元素使用内置函数delete完成

数据结构

  1. map的数据结构

一个Hash表中可以有多个bucket,每个bucket保存了map中的一个或多个键值对

1
2
3
4
5
6
7
8
// runtime/map.go:hmap
type hmap struct {
count int // 当前保存的元素个数
B uint8 // bucket数组的大小
buckets unsafe.Pointer // bucket数组, 2^B
oldbuckets unsafe.Pointer // 旧bucket数组,用于扩容

}
  1. bucket的数据结构
1
2
3
4
5
6
// runtime/map.go:bmap
type bmap struct {
tophash [8]uint8
data []byte
overflow *bmap
}

每个bucket可以存储8个键值对

  • tophash是一个长度为8的整型数组,Hash值低位相同的键存入当前bucket时会将Hash值的高位存储在该数组中,以便后续匹配。

扩容

触发条件

  • 负载因子大于6.5
  • overflow > 2^15

过程

  1. oldbuckets指向原buckets数组
  2. 申请新buckets = 2 * buckets
  3. 更新buckets指针
  4. 迁移数组
  5. 释放oldbuckets

增删改查

查找

  1. 根据key计算hash值

  2. hash低位 % hmap.B

  3. 取hash值高位,在tophash数组中查询

  4. 若tophash[i] == key.hash,则获取tophash[i]的key值进行比较

  5. 当前bucket中没有找到,则依次从溢出的bucket中查找

Struct

字段标签

Tag的本质

String

特点:string使用8比特字节的集合来存储字符,存储的是字符的UTF-8编码。在使用for-range遍历时,index可能不连续

1
2
3
4
5
6
7
8
9
func StringIteration() {
s := "中国"
for i, v := range s {
fmt.Printf("index: %d, value: %c\n", i, v)
}
}
// 输出
// 0, 中
// 3, 国

类型转换

string转[]byte

1
2
3
4
5
func StringToByte() {
b := []byte{'H', 'e', 'l','l','o'}
s := string(b)
fmt.Println(s)
}

[]byte转string

1
2
3
4
5
func ByteToString() {
s := "Hello"
b := []byte(s)
fmt.Println(b)
}

数据结构

1
2
3
4
5
// src/runtime/string.go:stringStruct
type stringStruct struct {
str unsafe.Pointer // 首地址
len int // 长度
}