一日一技: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 = a
a[0] = 'superman'
print(b)

运行效果如下图所示:

一日一技:Golang 字符串切片与 Python 列表的不同_数据_02

我们再来看看在 Golang 的效果:

b := a
a[0] = "superman"
fmt.Println(b)

运行效果如下图所示:

一日一技:Golang 字符串切片与 Python 列表的不同_数组_03

那么,我们是不是可以说,Golang 的切片就相当于 Python 里面元素数据类型相同的列表?

不同点

现在,我们再往列表和字符串切片里面各加一个元素,来看看运行效果:

在 Python 里面,运行效果如下图所示:

一日一技:Golang 字符串切片与 Python 列表的不同_字符串_04

进一步实验你会发现,a 和 b 两个列表是完全一样的,只要修改任何一个列表,另一个都会随之发生变化。

但是 Golang 里面并不是这样,如下图所示:

一日一技:Golang 字符串切片与 Python 列表的不同_数据_05

你修改任何一个切片,另一个切片都不会改变。

append

但实际上并不是这样,我们用另外一种初始化切片的方式来做一个测试:

一日一技:Golang 字符串切片与 Python 列表的不同_golang_06

在这个例子里面,我生成了一个长度为5,容量为20的字符串切片。根据第15-19行的运行结果可以看到,此时,无论是根据索引修改里面的元素,还是使用 append 添加新的元素,两个切片的变化都相同。如果我们把切片的容量调小,调整到6,再看看效果:一日一技:Golang 字符串切片与 Python 列表的不同_数据_07

testabcdea[0]

原因

字符串数组字符串切片
[5]string{"xx", "yy"}  // 这是长度为5的字符串数组
[]string{"xx", "yy"} // 字符串切片  
容量
a := make([]string, 5, 6)b := a[0: 6]

但是当a数据容量超过6以后,a 切片底层会重新生成一个长度为12的数组,并把原有的老数据都拷贝到新的数组里面,接下来的所有修改都是对这个新的数组进行修改。而此时 b 切片底层还是老的长度为6的数组,所以此时对 a 切片的修改就不会反映到 b 上面了。

 

一日一技:Golang 字符串切片与 Python 列表的不同_数组_08