golang面试必问之slice

224 阅读2分钟

golang面试必问之slice

题如下:

	a := make([]int, 0)
	a = append(a, 1)
	a = append(a, 4)
	a = append(a, 7)
	b := a
	b = append(b, 5)
	fmt.Println(a)
	fmt.Println(b)
	b = append(b, 6)
	a = append(a, 0)
	fmt.Println(a)
	fmt.Println(b)

我的错误回答,因为切片是指向同一个底层数组,所以,在改变变量的值的时候,两个变量值是一样的 真实答案: [1 4 7] [1 4 7 5 ] [1 4 7 0] [1 4 7 5 6]

第一次添加元素时,因为底层底层数组没有扩容,容量还为4,按照我的想法应该元素一致,但是实际是不一样的,所以这里就有一个疑问,这时两个变量不一样的地方是什么呢?我们打印两个变量的地址和长度,容量进行比较:

image.png 通过执行发现,两个变量的确指向同一地址,但是仅有长度不一致,所以此处说明,虽然两个切片变量指向数组地址一样,但是因为长度控制,两个变量所拥有的的值是有差别的。此处也说明,切片在有时在用一个地址去表示多个变量,为了节省内存,但是最后因为b 的扩容,两者的地址不一样了

此处引出第二个问题,如果在未扩容时,b 先再添加一个元素,a 再添加一个,此时会发生什么现象呢?

image.png 此时发现,a,b 变量地址,长度和容量都一样,会导致后面添加的,会覆盖前面添加的元素。 总结: slice 通过共用内存,达到节省空间的目的,同时也会让刚学习go的同学误认为切片是引用传递。其实其通过地址,长度和容量控制切片的最终值。