创建
1
2
3
4
5
6
7
8
| //1.make函数创建 (推荐)
切片名称 := make([]切片类型, 0, 指定容量)
//2.创建同时初始化 (有确定的数据时推荐)
var 切片名称 = []切片类型{}
//3.var常量定义 (不推荐)
var 切片名称 [] 切片类型
|
修改
值类型切片 → 必须拿索引才能改 指针切片 → 循环变量本身就是原对象地址,直接改即可
1
2
3
4
5
6
7
8
9
10
11
| // 必须按索引修改
dates := []Date{ {"666"}, {"777"} } // 非指针
for i := range dates {
dates[i].Id = "999" // 必须拿索引才能改
}
// 把切片元素换成指针直接改即可
dates := []*Date{ {"666"}, {"777"} } // 指针
for _, d := range dates {
d.Id = "999" // 直接改
}
|
切片存什么就改什么,指针共享值独立:
1
2
3
4
5
6
7
8
9
10
11
12
| type P struct{ V int }
{
a := &P{V: 1}
ptrSlice := []*P{a} // 存指针
valSlice := []P{*a} // 存副本/存值
a.V = 9 //修改a
fmt.Println(ptrSlice[0].V) // 9 (共享)
fmt.Println(valSlice[0].V) // 1 (独立)
}
|
append
list= append(list, elems)
- 如果你存的是值类型(
Sku),不需要临时变量; - 如果你存的是指针类型(
*Sku),就必须用临时变量,否则所有指针都指向同一个循环变量。
1
2
3
4
5
| var skusToUpdate []*sku.Sku //要指针
for _, skuInfo := range sdkSkus { // sdkSkus取出来
tempSku := skuInfo // 必须使用临时变量, range每次循环都把新值都指向同一个地址
skusToUpdate = append(skusToUpdate, &tempSku)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
| // 值类型:不用临时变量
list := []Sku{}
for _, s := range src {
list = append(list, s) // 每次 s都是新副本
}
// 指针类型:必须临时变量
list := []*Sku{}
for _, s := range src {
tmp := s // 必须拷贝
list = append(list, &tmp)
}
|
技巧
原地过滤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| filtered := numbers[:0]
for _, num := range numbers {
if isOdd(num) {
filtered = append(filtered, num)
}
}
/**
reports := ext.RsReports[:0] 的作用是创建一个空的切片,但复用原切片的底层数组。
原地删除第 i 个元素的经典写法:
ext.RsReports[:i] 拿到要保留的前半段(不含 i)
ext.RsReports[i+1:] 拿到后半段(不含 i)
append 把两段拼起来,重新赋给原切片变量,完成删除
ext.RsReports = append(ext.RsReports[:i], ext.RsReports[i+1:]...)
*/
|
最适用于以下情况:
- 在过滤后不再需要
numbers切片。 - 性能至关重要,特别是在处理大型数据集的时候。