1、前言
今天在网上看slice扩容原理,偶然看到一个slice的题目,感觉很有意思。题目如下:
package main
import "fmt"
func main() {
s1 := []int{1, 2}
s2 := s1
s2 = append(s2, 3)
Test1(s1)
Test1(s2)
fmt.Println(s1, s2)
}
func Test1(s []int) {
s = append(s, 0)
for i := range s {
s[i]++
}
}
选项如下:
A: [2,3] [2,3,4]
B: [1,2] [1,2,3]
C: [1,2] [2,3,4]
D: [2,3,1] [2,3,4,1]
看了看,这不是so easy嘛,直接选D。一看答案选C。
今天针对为什么选C做一个具体声明。
2、为什么调用Test1(s1),最后打印输出[1,2]
s1 := []int{1, 2}
Test1(s1)
fmt.Println(s1, s2)
我们一步一步来分析:
1. 首先将切片s1中存放的底层数组的内存地址,传入函数Test1()之后,切片s,就和切片s1指向同一个底层数组了。
2. 在Test1()函数里面进行了扩容,因为切片s1的长度为2,容量为2。所以扩容后的切片s指向新的底层数组。
3. 因切片s指向新的底层数组,所以切片s1的值没有任何改变。输出s1,仍未s1:[1,2]
3、为什么调用Test(s2),最后打印输出的[2,3,4]
func main() {
s1 := []int{1, 2}
s2 := s1
s2 = append(s2, 3)
Test1(s2)
fmt.Println(s1, s2)
}
func Test1(s []int) {
s = append(s, 0)
for i := range s {
s[i]++
}
}
同样一步步分析:
- 首先当把切片s1赋值给变量s2时,实际上是把切片s1中存放的底层数组的内存地址,赋值给变量 s2。赋值完成后,变量s2变为切片类型。和切片s1指向同一个底层数组。但,在使用append函数向切片s2中追加元素3时,由于切片s2指向的底层数组,长度为2,容量为2。所以,切片s2,指向新的底层数组。
- 此时切片s2长度为3,容量为4。因为刚开始容量为2时,进行了扩容。切片扩容一般是扩大2倍。所以此时
切片s2的长度为3,容量为4。
- 在函数Test()中,使用append函数在切片s中追加了一个元素0,切片s和切片s2指向同一个底层数组,(因为在传递函数参数的时候,传递的是切片s2中底层数组的内存地址),此时在运行for-range。切片s中值变为[2,3,4,1],==是不是想着切片s2也变为该值了?==答案错了
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)