当前位置: 首页 > 科技观察

【GoSlice详解】读者表示理解,终于看懂了Cap

时间:2023-03-12 16:28:12 科技观察

definevars1[]int//定义一个slice,存储int类型的元素vars2[]string//定义一个slice,存储int类型的元素typestringfmt.Println(s1,s2)fmt.Println(s1==nil)//true为空,没有创建内存空间内存空间,因为s1和s2的值为nil来声明和初始化,我们可以一边声明一边初始化vars1=[]int{1,2,3}vars2=[]string{"北园","长阳","望京"}fmt.Println(s1,s2)fmt.Println(s1==nil)//falsefmt.Println(s2==nil)//false打印结果:分析:初始化成功,s1和s2的值不相等nil的长度和容量使用len()和cap()分别获取切片的长度和容量fmt.Printf("len(s1):%dcap(s1):%d\n",len(s1),cap(s1))fmt.Printf("len(s2):%dcap(s2):%d\n",len(s2),cap(s2))printresult:parsing:符合我们的预期,length和capacity都是For3.从数组中获取切片我在本章开头已经提到了数组和切片的关系。这里我再进一步说:切片的本质是操作数组,但是数组是定长的,变长的切片是引用类型,可以理解为引用数组的一个片段;而数组是值类型,将数组A赋值给数组B会为数组B开辟新的内存空间,修改数组B的值不会影响数组A。作为引用类型,切片指向同一个内存地址,会互相影响。//定义一个数组a1:=[...]int{1,2,3,4,5,6,7,8,9}s3:=a1[0:4]//基于一个数组切[0:4]左边包含右边不包含是[1,2,3,4]fmt.Println(s3)打印结果:注:a1[0:4]是基于一个数组cut[0:4]leftcontainsandrightdoesnotcontain即[1,2,3,4]更多切割方法示例a1:=[...]int{1,2,3,4,5,6,7,8,9}s4:=a1[2:4]//[34]s5:=a1[:4]//[1234]s6:=a1[2:]//[3456789]s7:=a1[:]//[123456789]fmt.Println(s4)fmt.Println(s5)fmt.Println(s6)fmt.Println(s7)打印结果:分析:全部满足上述左包含,右不包含的原则s4从下标2截取,截取到下标4s5省略第一个参数,表示从下标0截取s6省略第二个参数,表示截取到最后一个元素s7省略两个参数,并且只填中间的冒号:,表示所有元素切片的长度和容量切片的长度很容易u理解,就是元素的个数。我们重点理解切片的容量:切片引用的底层数组中,从切片的第一个元素到数组最后一个元素的长度就是切片的容量。易于理解:a1:=[...]int{1,2,3,4,5,6,7,8,9}s5:=a1[:4]//[1234]s6:=a1[2:]//[3456789]s7:=a1[:]//[123456789]fmt.Printf("len(s5):%dcap(s5):%d\n",len(s5),cap(s5))//49fmt.Printf("len(s6):%dcap(s6):%d\n",len(s6),cap(s6))//77fmt.Printf("len(s7):%dcap(s7):%d\n",len(s7),cap(s7))//99打印结果:解析:a1是数组的长度是9,容量也是9,取值是从1到9s5/s6/s7是对数组a1进行切割得到的切片。s5的长度为4,因为1234只有4个元素,容量为9,因为s5的切片是从数组起始位置开始切的:第一个元素为1,最后一个元素为s5的底层数组a1为9,1到9共有9个元素,所以s5的容量为9。s6的长度为7,因为s6的元素为3-9的7个元素;容量也是7,因为s5的底层数组最后一个元素是9,3-9一共有7个元素,所以s6的容量是7。s7比较好理解。长度和容量都是9个,朋友们请自己理解。切片和重新切片我们可以重新切片切片。比如我们将上面的数据再次切片来测试s8:=s6[3:]//s8的值为:6789fmt.Printf("len(s8):%dcap(s8):%d\n",len(s8),cap(s8))//44打印结果:分析:我们知道可以再切片slice,至于长度和容器,大家应该明白了上面的栗子,这个输出是意料之中的。slice是引用类型下面举个例子来证明slice是引用类型//定义数组a1:=[...]int{1,2,3,4,5,6,7,8,9}//从数组中切出切片s6s6:=a1[2:]//[3456789]//切片再次切片赋值给s8s8:=s6[3:]//[6789]//修改原来的Array,将下标2的值由3改为333a1[2]=333//打印s6,发现s6中的3也变成了333fmt.Println("s6:",s6)//[333456789]//因为s8是在s6的基础上分片的,我们来测试一下fmt.Println("s8:",s8)//[6789]//我们把原数组下标为5的值由6变为666a1[5]=666//打印s8切片,结果6也变为666fmt.Println("s8:",s8)//[666789]printresult:分析:由此我们可以清楚的知道slice是一个引用类型。当底层数组发生变化时,无论是切片还是切片再切片,值都会发生变化。因为他们使用的是一块内存,指的是一个内存地址。小结本文介绍了切片的特性,如何定义切片,切片是否被数组切割,以及切片的引用类型特性。本文转载自微信公众号《程序员的升级打怪之旅》,作者“王中阳围棋”,可通过以下二维码关注。转载本文请联系《程序员升级打怪之旅》公众号。