先搞清楚Array和Slice的定义,Array 简单数组:是一组同类型元素的序列,序列长度也是数组定义的一部分。语法为:
1
Array := [ArrayLength] ElementType
不同长度的数组代表不同的数据类型:
1
2
3
4
5
6
7
arr1:=[3]string{}
arr2:=[6]string{}
fmt.Printf("type of arr1 is %s, the kind is %s\n",reflect.TypeOf(arr1),reflect.TypeOf(arr1).Kind())
fmt.Printf("type of arr2 is %s, the kind is %s\n",reflect.TypeOf(arr2),reflect.TypeOf(arr2).Kind())
//output
//type of arr1 is [3]string, the kind is array
//type of arr2 is [6]string, the kind is array
同时,Array在定义时,便给内部元素赋值为类型默认值。
1
arr :=[4]int
arr内存已经包含四个元素,其默认值为0。 当在定义Array时,如果无法确定长度,则可以使用”…“,来由实际元素个数确定数组长度:
1
b := [...]string{"Penn", "Teller"}
此时,数组b则由编译器检查其元素个数,确认其长度为2。
1
b := [2]string{"Penn", "Teller"}
实际两者等价。
Array一个重要的特性是:长度不可变。
那么如何满足可变长度的操作呢?最简单方式便使用Slice
Slice切片:一种提供丰富操作功能的元素序列,是对简单数组的高级抽象,是简单数组的强化版。实际切片内部也是对简单数据的引用,再提供高效的方式操作数组。其语法定义是:
1
SliceT := []ElementType
是不需要特别指定长度的,内部将包含容量、元素长度信息。
Array和Slice两者的差异
两者最大的差异是数组长度一旦确定便不可修改,无法变长,无法改短。而切片则通过伸缩容量。且数组是值类型,把一个数组赋予给另一个数组时是发生值拷贝,而切片是指针类型,拷贝的是指针。
下面通过一个实例来说明:代码如下: (1)是定义一个[3]int类型数组,依次赋值为1,2,3。 (2)将数组a赋值给b,将发生值拷贝。 (3)给数组a的下标2的元素赋值为4,这并不会影响数组b的内容。 (4)打印结果,得以说明情况。
1
2
3
4
5
6
7
8
9
10
11
//array
a:=[3]int{1,2,3}
b:=a
a[2]=4
fmt.Println("a = ", a)
fmt.Println("b = ", b)
fmt.Println(reflect.TypeOf(a).Kind())
// Output
// a = [1, 2, 4]
// b = [1, 2, 3]
// array
再看另一段代码:(1)不指定长度,(2)打印结果,显示有对a的修改影响了b的内容。
1
2
3
4
5
6
7
8
9
10
11
//slice
a:=[]int{1,2,3}
b:=a
a[2]=4
fmt.Println("a = ", a)
fmt.Println("b = ", b)
fmt.Println(reflect.TypeOf(a).Kind())
// Output
// a = [1, 2, 4]
// b = [1, 2, 4]
// slice
为何一个细微的变化有如此差异呢?这个便是Array和Slice定义时语法上的细微差异:
在括号中定义一个长度值,是编译器区别变量a数据类型的唯一依据,带长度值便是数组,不带便是切片。
可以通过 reflect.TypeOf(a).Kind() 判断是数组还是切片。
而且切片是引用传递,Array是值传递。
[] 是 slice,[n] 和 […] 都是 array。
Golang 绝大部分还是用到的是slice,普通程序里绝少有用到 Array 的地方。