Golang字符串切片和Python列表切片(Slice)的区别。这两个数据结构在形式上非常相似。今天我们来比较一个字符串列表和一个字符串切片。同样的一点,在Python中,我们定义一个字符串列表,初始值:a=['kingname','pm','xxx']在Golang中,我们定义一个字符串切片,初始值:a:=[]string{"kingname","pm","xxx"}接下来,我们分别在字符串列表和字符串切片的末尾添加几个元素:a.append("address")a.append("shanghai")在Golang中:a=append(a,"address")a=append(a,"shanghai")我们还可以给其他变量赋值,看一个是否被修改,另一个会被修改:b=aa[0]='superman'print(b)运行效果如下图:我们再看看Golang中的效果:b:=aa[0]="superman"fmt.Println(b)运行效果如图下图:那么,我们是否可以说Golang的切片就相当于Python中一个元素数据类型相同的列表?区别现在给list和stringslice加一个元素看看??运行效果:在Python中,运行效果如下图所示:进一步实验,你会发现a和b这两个list正是同样,只要修改了任何一个列表,另一个列表也会随之改变。但是在Golang中却不是这样,如下图所示:修改任意一个slice,其他slice都不会改变。看到这里,你可能会想,在Golang中,如果append添加新的数据,那么每次都会生成一个新的slice,所以添加数据后两个slice是不一样的。但事实并非如此,我们用另一种初始化切片的方式来做一个测试:在这个例子中,我生成了一个长度为5,容量为20的字符串切片。根据第15-19行的运行结果可以看出,此时无论是根据索引修改里面的元素,还是使用append添加新元素,两个切片的变化都是一样的。如果我们把slice的容量减到6,再看效果:从这里可以看出b跟在a后面变成了一半。a新添加的测试字符串在b中也可以找到。但是a中新加的abcde并没有出现在b中。而对a[0]的修改并没有出现在b中。Golang的切片之所以会出现这种现象,首先要从数组和切片的区别说起。在Golang中,字符串数组和字符串切片很相似,但是它们有一个根本的区别,就是数组的长度需要在开头声明,不能扩展。slice不需要声明长度,所以:[5]string{"xx","yy"}//这是一个字符串数组,长度为5[]string{"xx","yy"}//Stringslice切片的底层还是一个数组,切片有一个容量的概念,指的是底层数组的长度。如果切片中的数据量等于切片的容量,那么下次加入新数据时,切片的底层会创建一个两倍于原来长度的文件(当数据量较少时大于1024时为2倍,大于1024时为1.25倍),然后按顺序复制现有数据,再插入新数据。那么,回到上面的代码。当我们使用a:=make([]string,5,6)创建一个容量为6的字符串切片时,它会在底部初始化一个长度为6的字符串数组。当代码执行到b:=a[0:6]时,这里的b虽然是另外一个slice,和a的内存地址不同,但是共享同一个底层数组。只要数据小于6,修改其中一个切片的数据本质上就是修改它的底层数组,而另一个切片也使用这个数组,所以这个修改也能看出来。但是当a的数据容量超过6时,切片a的底层会重新生成一个长度为12的数组,并将原来的旧数据复制到新数组中,之后所有的修改都会对这个新数组进行修改。此时b切片的底层仍然是长度为6的老数组,所以此时a切片的修改不会反映到b上。
