golang面试题(3):切片使用陷阱

问题1:下面程序输出结果

package main
import "fmt"
func main() {
	a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	b := a[2:5]
	c := b[2:6:7]
	c = append(c, 100)
	c = append(c, 200)
	b[2] = 20
	fmt.Println(b)
	fmt.Println(c)
	fmt.Println(a)
}
##输出
[2 3 20]
[4 5 6 7 100 200]
[0 1 2 3 20 5 6 7 100 9]

原因

1: b 从 a 索引2到索引5(左闭右开原则,元素为2,3,4),长度为3,容量默认到数组结尾,为82: c从 b的索引2 到索引6(开区间,元素为4,5,6,7), 容量到索引7(开区间,真正到索引6),为53: 接着,向 c 尾部追加一个元素 100,c容量刚好够,直接追加。
4: 不过,这会修改原始数组对应位置的元素。这一改动,数组和 b都可以看得到。
5: 再次向 c追加元素200,这时,c 的容量不够用,该扩容了。于是,c 将原来的元素复制新的位置,扩大自己的容量。并且为了应对未来可能的 append 带来的再一次扩容,c会在此次扩容的时候多留一些 buffer,将新的容量将扩大为原始容量的2倍,也就是10了。
6: 最后,修改 b索引为2位置的元素:b[2] = 20。 由于只会影响原始数组的元素,而c已经扩容变成新数组,故不会影响c

考察点

  • 切片复杂表达式
    • slice表达式分为简单表达式 a[low , high] 和扩展表达式 a[low : high : max]
    • 扩展表达式中的max用于限制新生成切片的容量,新切片的容量为 max-low,表达式中low、high 和max的关系需要满足如下: o <= low <= high <= max <= cap(a)
  • 切片底层数组共享
    • 简单表达式生成的切片与原数组或者切片共享底层数组避免了拷贝元素,节约内存空间的同时,也会带来读写冲突的风险。新切片b( b := a[low : high] ) 不仅可以读写a[low] 到 a[high-1]之间的元素,而且在使用append(b,x)函数增加新元素x时,还可能会覆盖a[high]以及后面的元素
  • 切片扩容
    • 使用append()向切片追加元素时有可能会发生扩容现象,扩容后会生成新的切片
    • 扩容容量的选择遵循一下基本规则
      • 如果原slice的容量小于1024(1.18版本调整为256),则新slice的容量将扩容到2倍
      • 如果原slice的容量大于等于1024(1.18版本调整为256),则新slice的容量将扩容1.25倍
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董洪臣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值