由一道关于Go切片的题目引出的有趣讨论

话不多说,首先上题。请观察以下几行代码,并说出打印结果:

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

很简单的几行代码,但是却要求对go语言的slice切片类型进行深入理解。一般人首先第一反应给出的答案是[2,3,5],来看看实际上的答案:

[1 2 3 5]

接下来对这几行代码进行详细讲解:

首先,切片是一个引用类型,其本质就是对底层数组的封装,它包含了三个信息(相当于一个结构体):底层数组的指针、切片的长度(len)和切片的容量(cap)

在上述代码中,我们初始化了一个切片,其结构如下,array指向一个底层数组;

然后,将切片s通过值传递给变量t,(注意,Go里面只有值传递),然后于是变量t也有了s的这些属性值,即 len(t)=4,cap(t)=4,array指针指向与s同一个底层数组,已经赋值完毕后,不管后续s再如何操作,t的这三个成员变量值不会再发生变化,所以唯一会受到影响的是其底层数组的指针指向的数组值。

再接下来是这行代码:

s = append(s[1:3], 5)

这时发生了三件事:取底层数组的切片[1:3], 然后将5放在该切片的后面,最后将新的切片属性赋值给s。(这里要注意,不管如何操作,操作的都是同一个底层数组,底层数组的地址空间一直就摆在那里),如下图所示。

由于元素3后面已经开辟过空间地址了,所有5添加进来的时候,直接会将这块地址指向的字面值重新赋值为5,相当于将4给覆盖了。于是底层数组的值此时就变成了[1,2,3,5],

所以不管s再如何操作,t的成员变量值不再发生变化,即其底层数组的指针指向不变,只是数组值变成了[1,2,3,5]而已。

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值