Go面试题关于 array 和 slice 一个问题
Posted 小生凡一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go面试题关于 array 和 slice 一个问题相关的知识,希望对你有一定的参考价值。
文章目录
写在前面
最近有同学问我这个问题啊,以下两个函数输出了什么?
func arrayTest()
a := [3]int1, 2, 3
for k, v := range a
if k == 0
a[0], a[1] = 100, 200
a[k] = 100 + v
fmt.Println(a)
func sliceTest()
a := []int1, 2, 3
for k, v := range a
if k == 0
a[0], a[1] = 100, 200
a[k] = 100 + v
fmt.Println(a)
先给结论
- 数组:[101,102,103]
- 切片:[101,300,103]
题解
众所周知,Go里面都是值传递,就算是引用类型也是传地址。
我们先了解一下一些数据结构
队列:先进先出
栈:先进后出,在程序调用的时候从栈空间去分配
堆:在程序调用的时候从系统的内存区分配
值类型: 变量直接存储值,内容通常在栈中分配
引用类型: 变量存储的是一个地址,这个地址存储最终的值,内容通常在堆上分配,通过GC回收
那么Go的值传递和引用类型又有哪些?
值类型:基本数据类型int
,float
,bool
,string
,数组
和struct
引用类型:指针
,slice
,map
,chan
等都是引用类型
知道数组是值传递,切片是引用我们就清楚了。
数组只是传递值,相当于深拷贝,无论怎么改变都并不影响原值,而切片是传递地址,改变就会跟着改变
看看这个例子
var x[4]int = [4]int1,2,3,4
var y[4]int = x
fmt.Println(x,y)
y[0]=123
fmt.Println(x,y)
结果
[1 2 3 4] [1 2 3 4]
[1 2 3 4] [123 2 3 4]
我们可以看到这个数组的改变并不影响原来的数组,那么当我们将这个数组变成切片的时候。
var x[]int = []int1,2,3,4
var y[]int = x
fmt.Println(x,y)
y[0]=123
fmt.Println(x,y)
结果
[1 2 3 4] [1 2 3 4]
[123 2 3 4] [123 2 3 4]
当我们改变切片的时候,是都变了。
回到这道题上
那么我们知道 数组是值传递,切片是引用传递
func arrayTest()
a := [3]int1, 2, 3 // 数组
for k, v := range a
if k == 0
a[0], a[1] = 100, 200 // 改变了
a[k] = 100 + v // 之后又改变了
fmt.Println(a)
所以上面的数组就可以理解为是临时改变了,但是原地址上面的还是原来的值
我们 debug 一下就更清楚了
- 初始状态
- 第一次改变
我们发现原来数组a的前两位已经发生了改变
- 第二次改变
- 第三次改变
其实我们把 k,v 打印出来就明显很多了,k v从始至终都没有改变过
那么换成切片是什么样子呢?
func sliceTest()
a := []int1, 2, 3
for k, v := range a
if k == 0
a[0], a[1] = 100, 200
a[k] = 100 + v
fmt.Println(a)
同样debug一下,就很清楚了
注意第一次循环的话,这个v的值是1
!!因为已经定下来了
切片的值也已经变了,但是此时v是1!所以这个a[0]=100+1
。 而当下一个之后v就变成200了!!
所以这个300就是这样来的!
所以这里要考察的是go的值传递和引用类型的区别。
参考链接
以上是关于Go面试题关于 array 和 slice 一个问题的主要内容,如果未能解决你的问题,请参考以下文章