文章

切片

创建

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切片。
  • 性能至关重要,特别是在处理大型数据集的时候。

© 2024- lfj