Golang复习笔记之Slice(面向面试)

1. 基本概念

Slice 是 Go 语言中动态大小的数组,是对数组的引用。
Slice 与数组的区别:

  • 数组的长度固定,创建时就已确定;而 slice 是动态的,可以根据需要自动扩展。

声明和初始化 slice:

- var s []int  //未初始化的slice

- s := []int{1, 2, 3, 4, 5} //字面量初始化slice

- s := make([]int, 5)  //make创建silce,长度和容量相同

- s := make([]int, 5, 10) //长度和容量不同

- arr := [5]int{1, 2, 3, 4, 5}     //定义数组,从数组中取得silce
  s := arr[1:4]  

- var s []int            // 零值 slice,通过append初始化slice
  s = append(s, 1, 2, 3)
  
- s := [][]int{//多维slice
   {1, 2, 3},
   {4, 5, 6},
   {7, 8, 9},
}

2. 底层原理

Slice 本质上是一个结构体,包含三个部分:指向底层数组的指针(pointer)、长度(len)、容量(cap)。
动态扩容当 slice 的容量不够时,Go 会分配一个更大的底层数组,并将现有的元素复制到新的数组上。

3. 容量与长度

获取长度和容量:

  • len(slice) 获取长度,使用 cap(slice) 获取容量。
    增加或减少长度:
  • 通过 append() 函数向 slice 添加元素会自动增加长度;减少长度可以通过重新切片来实现,例如 slice = slice[:len(slice)-1]。

4. 切片操作

slice[start:end] 的含义:

  • slice[start:end] 表示从索引 start 到索引 end(不包括 end),截取原 slice 的一部分。
    添加元素:
  • 通过 append 向 slice 添加元素: slice = append(slice, value)。

5. slice 的共享特性

如果多个 slice 共享同一个底层数组,那么修改一个 slice 中的元素可能会影响其他 slice。也可能导致“内存泄漏”风险,当其他部分仍然引用旧的数组时,内存无法被释放。

6. 深浅拷贝

浅拷贝和深拷贝:

  • 浅拷贝可以直接赋值,但两个 slice 共享相同的底层数组;深拷贝需要使用 copy() 函数,如 copy(dest, src)。

7. slice 的陷阱

slice 的常见陷阱或边界情况:

  • 多个 slice 共享同一个底层数组,修改其中一个 slice 的内容可能会影响其他 slice。
  • append() 操作可能导致底层数组重新分配,原 slice 的修改不再影响新 slice。
  • 切片容量不足:如果 slice 反复扩容,每次 append() 都会导致底层数组重新分配和数据拷贝,导致性能问题。
  • 截取 slice 时,即使只保留少量数据,底层数组仍然可能被保留,导致无法释放内存。
  • 索引越界:对 slice 进行切片时,索引不合法会导致程序 panic。
  • 因为 slice 传递的是引用,因此 modifySlice 函数中对 slice 的修改也会影响到外部的 slice。
  • 零值 slice 是合法的,只是在使用之前没有分配内存,但是 append() 会自动处理这些情况。
  • 在循环中频繁使用 append() 和 copy() 可能导致不必要的性能损耗。

8. slice 在函数中的传递

slice 是按引用传递的,因为它内部包含了一个指针指向底层数组。array是值传递。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值