append

切片有三个属性,指针 (ptr)、长度 (len) 和容量 (cap)。append 时有两种场景:
  • 当 append 之后的长度小于等于 cap,将会直接利用原底层数组剩余的空间。
  • 当 append 后的长度大于 cap 时,则会分配一块更大的区域来容纳新的底层数组。
因此,为了避免内存发生拷贝,如果能够知道最终的切片的大小,预先设置 cap 的值能够获得最好的性能。
 

delete

切片的底层是数组,因此删除意味着后面的元素需要逐个向前移位。每次删除的复杂度为 O(N),因此切片不合适大量随机删除的场景,这种场景下适合使用链表。
 

Insert

insert 和 delete 类似。即在某个位置添加一个元素后,将该位置后面的元素再 append 回去。复杂度为 O(N)。因此,不适合大量随机插入的场景。
 

Filter

当原切片不会再被使用时,就地 filter 方式是比较推荐的,可以节省内存空间。
 

Push

在末尾追加元素,不考虑内存拷贝的情况,复杂度为 O(1)。 在头部追加元素,时间和空间复杂度均为 O(N),不推荐。
 

Pop

尾部删除元素,复杂度 O(1)
 

性能问题:

在已有切片的基础上进行切片,不会创建新的底层数组。因为原来的底层数组没有发生变化,内存会一直占用,直到没有变量引用该数组。因此很可能出现这么一种情况,原切片由大量的元素构成,但是我们在原切片的基础上切片,虽然只使用了很小一段,但底层数组在内存中仍然占据了大量空间,得不到释放。比较推荐的做法,使用 copy替代 re-slice