之前我有写过一篇关于slice的博客——slice理解。其中是对slice的底层结构,扩展,以及range关键字进行解析,而现在刚好又碰到一个关于slice的问题,算是自己粗心犯的一个错吧。

slice初始化

一般来说slice的初始化方式可以有两种:

  • 通过数组来初始化
  • 通过内置函数make()初始化
1
2
3
4
5
6
s :=[]int{1,2,3 } 
直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3.其cap=len=3
s := arr[:]
初始化切片s,是数组arr的引用
s := arr[:endIndex]
缺省startIndex时将表示从arr的第一个元素开始到第endIndex个元素

所以说,若是直接声明一个slice,是不可用的。

1
var s []int

所以,为了偷懒,我一般是使用make的方式。

问题出现

我有些忘记了make函数创建slice时,返回的是一个已被填充好值的slice,但我依然习惯性的使用了append去添加元素,这样会导致slice数据出现冗余,类似于这样的代码:

1
2
3
4
5
func main() {
s := make([]int, 5)
s = append(s, 1, 2, 3)
fmt.Println(s)
}

代码运行结果是:

1
[0 0 0 0 0 1 2 3]

为什么?

1
func make([]T, len, cap) []T

其中T代表被创建的切片元素的类型。函数 make 接受一个类型、一个长度和一个可选的容量参数。调用 make 时,内部会分配一个数组,然后返回数组对应的切片。

1
2
3
var s []byte
s = make([]byte, 5, 5)
// s == []byte{0, 0, 0, 0, 0}

当容量参数被忽略时,它默认为指定的长度。下面是简洁的写法:

1
s := make([]byte, 5)

所以说,当继续使用append时,数据时直接填充在这些默认值0的后面的,这也就造成实际数据中出现多余的0,从而影响后续的操作。

附加

slice追加到另一个slice

如果将一个slice追加到另一个slice中需要带上"",这样才能表示是将slice中的元素依次追加到另一个slice中。

1
s :=append(s,s1...)

在通过下标访问元素时下标不能超过len大小,如同数组的下标不能超出len范围一样。

删除切片元素

1
2
index := 5
ss = append(ss[:index], ss[index+1:]...)