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

一篇文章带你了解Go语言基础之切片补充

时间:2023-03-12 18:34:14 科技观察

一篇文章带你了解Go语言基础之slice补充make解惑我们知道slice可以通过make来创建。varnames=make([]string,10,10)这句话的意思是动态创建一个slice,slice的元素个数是10,slice的容量也是10,有没有疑惑???切片的数量和容量是多少???他们之间是什么关系???切片的本质其实就是一个存储数据的东西。目前,我们知道数组可以存储东西。其实切片的本质还是数组,只是Go帮我们做了一些封装,可以方便的对切片中的数据进行增删改查。例如:packagemainimport"fmt"funcmain(){varnames=make([]int,4,10)//int类型默认值为0fmt.Println(names,len(names),cap(names))//result:[0000]410}理解图形。没错,本质就是指向一个更长的数组。但是这个数组会自动扩展。当capacity(cap)append满了,会自动扩容。现在,我们知道make中参数的含义了。注意:在Go中,建议使用make创建分片,创建分片时需要考虑容量,尽量不触发容量自动扩容机制,以提高性能。为什么sliceappend前面有一个空格?在上一章中,大概有这么一段代码。packagemainimport"fmt"funcmain(){varnames=make([]int,5,10)names=append(names,11,23,231)fmt.Println(names)//[000001123231]}append之后,前面会出现很多0,这是怎么回事。说明:通过make创建切片时,第二个参数为切片元素个数。上面代码slice的第二个参数是5,也就是说在创建slice的时候,前5个已经有值了,但是int的默认值是0。所以追加的时候,在原来的基础上加上值,直到cap满,触发扩容机制。如图所示。现在,清楚了吗?那追加的时候怎么从0开始呢???这个不是很简单,直接让第二个参数为0。varnames=make([]int,0,10)//结果:[1123231]如图所示。好了,这个,我明白了,怎么继续。为什么不推荐使用var[]类型的方法创建切片我们上面一直提到一个词,自动扩容。我们来看这样一段普通的代码。packagemainimport"fmt"funcmain(){varnames[]int//address:0x0,length(len):0,capacity(cap):0fmt.Printf("address:%p,length(len):%d,capacity(cap):%d\n",names,len(names),cap(names))names=append(names,1,2,3)//address:0xc000010380,length(len):3,Capacity(cap):4fmt.Printf("address:%p,length(len):%d,capacity(cap):%d\n",names,len(names),cap(names))}whilefollowing这样使用append动态添加就没有问题了。没有make声明数组时,len和cap都是0,地址也是一个值。append之后可以很明显的看到地址变了,因为重新申请了数组,slice又重新指向了新的数组。len和cap也发生了变化。copycopyslicepackagemainimport"fmt"funcmain(){varnames1=make([]string,0,10)names1=append(names1,"张三")names1=append(names1,"李四")varnames2=names1//将names1赋值给names2fmt.Println(names1,names2)//[张三李四][张三李四]names1[0]="张三666"//修改names的值下标为0asZhangSan666fmt.Println(names1,names2)//[张三666李四][张三666李四]//为什么修改names1的值会影响names2的值????}为什么修改names1的值会影响names2的值???这个,我们还得回到内存分布图,如图。我们说过很多次,不管是打印、赋值还是其他操作,只会操作栈中存储的值。当names2=names1时,只会将names1在栈上的地址赋给names2。但是保存的时候,堆上的地址终究还是指向同一个堆。所以当names1被修改时,names2也会被修改。那么不想出现以上问题怎么办???解决方法:使用copypackagemainimport"fmt"funcmain(){varnames1=make([]string,0,10)names1=append(names1,"张三")names1=append(names1,"Lisi")//定义一个用于接收的names2slice,第二个参数要留空,names1中有几个元素,names2的第二个参数也应该是多少varnames2=make([]string,2,10)copy(names2,names1)//将names1的值赋给names2fmt.Println(names1,names2)//[张三李四][张三李四]names1[0]="张三666"//修改names的下标为0as张三666fmt.Println(names1,names2)//[张三666李四][张三李四]fmt.Printf("names1地址:%pnames2地址:%p\n",names1,names2)//names1address:0xc00009a0a0names2address:0xc00009a140}memorymap:自动扩展机制很抱歉,我不会。..综上所述,我们学习了Go基础的切片补充。如果在操作过程中遇到任务问题,记得在下方讨论区留言,我们看到会第一时间解决。