Go Quiz: 从Go面试题看slice的底层原理和注意事项

面试题

最近Go 101的作者发布了11道Go面试题,非常有趣,打算写一个系列对每道题做详细解析。欢迎大家关注。

大家可以看下面这道关于slice的题目,通过这道题我们可以对slice的特性和注意事项有一个深入理解。

package main
​
import "fmt"
​
func main() {
  a := [...]int{0, 1, 2, 3}
  x := a[:1]
  y := a[2:]
  x = append(x, y...)
  x = append(x, y...)
  fmt.Println(a, x)
}
  • A: [0 1 2 3] [0 2 3 3 3]

  • B: [0 2 3 3] [0 2 3 3 3]

  • C: [0 1 2 3] [0 2 3 2 3]

  • D: [0 2 3 3] [0 2 3 2 3]

大家可以在评论区留下你们的答案。这道题有几个考点:

  1. slice的底层数据结构是什么?给slice赋值,到底赋了什么内容?

  2. 通过:操作得到的新slice和原slice是什么关系?新slice的长度和容量是多少?

  3. append在背后到底做了哪些事情?

  4. slice的扩容机制是什么?

解析

我们先逐个解答上面的问题。

slice的底层数据结构

talk is cheap, show me the code. 直接上slice的源码:

slice定义在src/runtime/slice.go第15行,源码地址:go/slice.go at master · golang/go · GitHub

Pointer定义在src/unsafe/unsafe.go第184行,源码地址:go/unsafe.go at master · golang/go · GitHub

type slice struct {
  array unsafe.Pointer
  len   int
  cap   int
}
​
type Pointer *ArbitraryType

slice实际上是一个结构体类型,包含3个字段,分别是

  • array: 是指针,指向一个数组,切片的数据实际都存储在这个数组里。

  • len: 切片的长度。

  • cap: 切片的容量,表示切片当前最多可以存储多少个元素,如果超过了现有容量会自动扩容。

因此给slice赋值,实际上都是给slice里的这3个字段赋值。看起来这像是一句正确的废话,但是相信我,记住这句话可以帮助你非常清晰地理解对slice做修改后slice里3个字段的值是怎么变的,slice 指向的底层数组的数据是怎么变的。

:分割操作符

:分割操作符有几个特点:

  1. :可以对数组或者slice做数据截取,:得到的结果是一个新slice

  2. slice结构体里的array指针指向原数组或者原slice的底层数组,新切片的长度是右边的数值减去左边的数值,新切片的容量是原切片的容量减去:左边的数值。

  3. :的左边如果没有写数字,默认是0,右边没有写数字,默认是被分割的数组或被分割的切片的长度。

    a := make([]int, 0, 4) // a的长度是0,容量是4
    b := a[:] // 等价于 b := a[0:0], b的长度是0,容量是4
    c := a[:1] // 等价于 c := a[0:1], b的长度是1,容量是4
    d := a[1:] // 编译报错 panic: runtime error: slice bounds out of range
    e := a[1:4] // e的长度3,容量3
  4. :分割操作符右边的数值有上限,上限有2种情况

  • 如果分割的是数组,那上限是是被分割的数组的长度。

  • 如果分割的是切片,那上限是被分割的切片的容量。注意</

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值