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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
package slice000
import (
"testing"
commonprint "github.com/gainovel/testcase/tools/common/print"
)
var (
myfmt = commonprint.MyFmt
)
func TestName_2024_01_09_18_10_28(t *testing.T) {
// panic的情况:①索引超出范围。
// go test -v -run TestName_2024_01_09_18_10_28/index_out_of_range github.com/gainovel/testcase/stdlib/runtime/slice
// Result👉panic: runtime error: index out of range [1] with length 1
t.Run("index out of range", func(t *testing.T) {
var (
s1 []int
)
s1 = make([]int, 0, 5)
s1 = append(s1, 1)
myfmt.VarInitPrintln(`var (
s1 []int
)`)
myfmt.ColorDescPrintln("s1 = make([]int, 0, 5);s1 = append(s1, 1)")
myfmt.KeyValuePrintln("s1", s1, "s1[0]", s1[0])
myfmt.KeyValuePrintln("s1[1]", s1[1])
})
// 1.多个slice可能共享同一底层数组。
// 2.简单表达式(s1[low:high]),简单表达式切片并未限制新的slice的容量,
// 也就是说通过内置函数append()添加新元素时有覆盖原数组或者原slice元素的风险
// go test -v -run TestName_2024_01_09_18_10_28/share_array github.com/gainovel/testcase/stdlib/runtime/slice
t.Run("share array", func(t *testing.T) {
var (
s1 []int
s1_1 []int
s2 []int
s2_1 []int
)
s1 = []int{1, 2, 3, 4, 5}
s2 = []int{1, 2, 3, 4, 5}
s1_1 = s1[1:3]
s2_1 = s2[1:3:3]
myfmt.VarInitPrintln(`var (
s1 []int
s1_1 []int
s2 []int
s2_1 []int
)`)
myfmt.ColorDescPrintln("s1 = []int{1, 2, 3, 4, 5};s1_1 = s1[1:3]", "s2 = []int{1, 2, 3, 4, 5};s2_1 = s2[1:3:3]")
myfmt.KeyValuePrintln("s1", s1, "len(s1)", len(s1), "cap(s1)", cap(s1),
"s1_1", s1_1, "len(s1_1)", len(s1_1), "cap(s1_1)", cap(s1_1))
myfmt.KeyValuePrintln(
"s2", s2, "len(s2)", len(s2), "cap(s2)", cap(s2),
"s2_1", s2_1, "len(s2_1)", len(s2_1), "cap(s2_1)", cap(s2_1))
s1_1 = append(s1_1, 100)
s2_1 = append(s2_1, 100)
myfmt.ColorDescPrintln("s1_1 = append(s1_1, 100)", "s2_1 = append(s2_1, 100)")
myfmt.KeyValuePrintln("s1", s1, "len(s1)", len(s1), "cap(s1)", cap(s1),
"s1_1", s1_1, "len(s1_1)", len(s1_1), "cap(s1_1)", cap(s1_1))
myfmt.KeyValuePrintln(
"s2", s2, "len(s2)", len(s2), "cap(s2)", cap(s2),
"s2_1", s2_1, "len(s2_1)", len(s2_1), "cap(s2_1)", cap(s2_1))
})
// go test -v -run TestName_2024_01_09_18_10_28/slice_copy github.com/gainovel/testcase/stdlib/runtime/slice
t.Run("slice copy", func(t *testing.T) {
var (
s1 []int
s2 []int
)
s1 = []int{1, 2, 3, 4, 5}
s2 = []int{100, 100, 100}
myfmt.VarInitPrintln(`var (
s1 []int
s2 []int
)`)
myfmt.ColorDescPrintln("s1 = []int{1, 2, 3, 4, 5}", "s2 = []int{100, 100, 100}")
myfmt.KeyValuePrintln("s1", s1, "s2", s2)
copy(s2, s1)
myfmt.ColorDescPrintln("copy(s2, s1)")
myfmt.KeyValuePrintln("s1", s1, "s2", s2)
s1 = []int{1, 2, 3, 4, 5}
s2 = []int{100, 100, 100}
myfmt.ColorDescPrintln("s1 = []int{1, 2, 3, 4, 5}", "s2 = []int{100, 100, 100}")
myfmt.KeyValuePrintln("s1", s1, "s2", s2)
copy(s1, s2)
myfmt.ColorDescPrintln("copy(s1, s2)")
myfmt.KeyValuePrintln("s1", s1, "s2", s2)
})
// slice扩容规则:
//1.slice扩容时有几个关键的值需要提前说明一下:
// 👉oldCap:扩容前容量、oldLen:扩容前元素个数、cap:扩容所需最小容量、newCap:预估容量
//2.Go1.15扩容规则👉如果oldCap(扩容前的容量)翻倍之后还是小于cap(扩容所需最小容量),
// 那么newCap(预估容量)就等于cap(扩容所需最小容量),
// 如果不满足第一条,而且oldLen(扩容前元素个数)小于1024,那么newCap(预估容量)=oldCap(扩容前的容量)*2,
// 如果不满足第一条,而且oldLen(扩容前元素个数)大于等于1024,那就循环扩容四分之一,直到大于等于所需最小容量
//3.Go1.16扩容规则👉Go1.16中有了些变化,和1024比较的不再是oldLen(扩容前元素个数),而是oldCap(扩容前的容量);
//4.Go1.18扩容规则👉到了Go1.18时,又改成不和1024比较了,而是和256比较;并且扩容的增量也有所变化,除了每次扩容1/4,还得加上256*3/4
//5.预估容量不一定为最终申请的容量;Go的内存管理,申请内存时都有一定的规格(8,16,32,48…),
// e.g. int类型slice,预估容量为5,64位操作系统,需要申请40字节,
// 但内存规格中不存在40,Go的内存管理会帮我们匹配到足够大、且最接近的规格48,最终申请的容量是6。
// go test -v -run TestName_2024_01_09_18_10_28/expansion_experiment github.com/gainovel/testcase/stdlib/runtime/slice
t.Run("expansion experiment", func(t *testing.T) {
var (
s1 []int
s2 []int
)
s1 = make([]int, 0, 1)
s2 = make([]int, 0, 1)
myfmt.VarInitPrintln(`var (
s1 []int
s2 []int
)`)
myfmt.ColorDescPrintln("s1 = make([]int, 0, 1)", "s2 = make([]int, 0, 1)")
myfmt.KeyValuePrintln("s1", s1, "len(s1)", len(s1), "cap(s1)", cap(s1))
myfmt.KeyValuePrintln("s2", s2, "len(s2)", len(s2), "cap(s2)", cap(s2))
s1 = append(s1, 1, 2, 3, 4)
s2 = append(s2, 1, 2, 3, 4, 5)
myfmt.ColorDescPrintln("s1 = append(s1, 1, 2, 3, 4)", "s2 = append(s2, 1, 2, 3, 4, 5)")
myfmt.KeyValuePrintln("s1", s1, "len(s1)", len(s1), "cap(s1)", cap(s1))
myfmt.KeyValuePrintln("s2", s2, "len(s2)", len(s2), "cap(s2)", cap(s2))
})
}
|