forked from Junedayday/code_reading
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathslice.go
More file actions
89 lines (74 loc) · 2.31 KB
/
slice.go
File metadata and controls
89 lines (74 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package main
import (
"fmt"
"unsafe"
)
func slice() {
fmt.Println("Slice Init")
var s []int
// Tip: 对比一下map和slice的make函数,前者在类型后可跟0个或1个参数,而后者是1个和2个参数
s = make([]int, 2)
fmt.Println(len(s), cap(s))
s = make([]int, 2, 4)
fmt.Println(len(s), cap(s))
// Tip: 元素个数小于cap时,append不会改变cap,只会增加len
fmt.Println("Slice Assign")
s[0] = 1
s[1] = 2
s = append(s, 4)
fmt.Println(len(s), cap(s))
// Tip: 元素个数超过cap时,会进行扩容
s = append(s, 8, 16)
fmt.Println(len(s), cap(s))
// Tip: Slice没有显式的删除语句
fmt.Println("Slice Delete")
s = append(s[0:1], s[2:]...)
fmt.Println(s)
fmt.Println("Slice Range")
for i, v := range s {
fmt.Println(i, v)
fmt.Printf("%p %p\n", &i, &v)
}
}
/*
slice 的源码部分
slice基础结构slice:
包括保存数据的array、长度len与容量cap
初始化函数makeslice:
math.MulUintptr:根据元素大小和容量cap,计算所需的内存空间
mallocgc: 分配内存, 32K作为一个临界值,小的分配在P的cache中,大的分配在heap堆中
扩容growslice:
当长度小于1024时,cap翻倍;大于1024时,增加1/4。 但这个并不是绝对的,会根据元素的类型尽心过一定的优化
拷贝slicecopy:
核心函数为memmove,from=>to移动size大小的数据,size为 元素大小 * from和to中长度较小的个数
拷贝slicestringcopy:
基本与上面类似,字符串的拷贝
*/
func sliceAddr() {
fmt.Println("Part 1")
var s = make([]int, 2, 2)
s[0] = 1
fmt.Println(unsafe.Pointer(&s[0]))
s[1] = 2
fmt.Println(unsafe.Pointer(&s[0]))
// Tip: 扩容后,slice的array的地址会重新分配
s = append(s, 3)
fmt.Println(unsafe.Pointer(&s[0]))
fmt.Println("Part 2")
// Tip: a虽然是一个新的地址,但指向的array是和a一致的
a := s[:2]
fmt.Printf("%p %p\n", &s, &a)
fmt.Println(unsafe.Pointer(&a[0]))
a[0] = 2
fmt.Println(a, s)
// Tip: 如果要进行slice拷贝,使用copy方法
b := make([]int, 2)
copy(b, s)
fmt.Printf("%p %p\n", &s, &b)
fmt.Println(unsafe.Pointer(&b[0]))
fmt.Println("Part 3")
// Tip: sNil的array指向nil,而sEmpty的array指向一个内存地址
var sNil []int
var sEmpty = make([]int, 0)
fmt.Println(len(sNil), len(sEmpty), cap(sNil), cap(sEmpty))
}