0. 引言
C中只有数组的概念,没有切片的概念;Python中只有切片的概念,没有数组的概念;Go语言同时拥有数组和切片的概念,这两者看起来没什么区别都直接通过[x]int来使用,但实际上有很多不同的点。
1. 数组
1.1 什么是数组及其类型
数组,一言以蔽之:定长的同类型数据集合。
即数组的长度是固定的且数组内的元素类型相同。关键的点就在于这个长度是否是固定。因为在Go语言中数组类型是包括长度以及类型,如:
var a[100]int // 数据类型为 [100]int
var b[365]int // 数据类型为 [365]int
要知道,不同类型之间是不能通过=
赋值的,也就是说在上面的情况下,若添加上一句a = b
会发生编译错误。
1.2 “不定”数组及其类型
特殊的,如果不确定数组的长度,可以使用Go语言的...
语法糖。通过以下操作来声明一个数组:x := [...]int{11,22}
,此时x的数据类型为[2]int
。
注意在使用[...]int来定义一个不确定长度的数组时必须直接赋值,因为在本质上通过语法糖来定义的数组虽然可以存放任意个数,但仍需要确定长度(定义结束即为确定长度)。
如果没有直接把数据传入var m = [...]int{}
之中的m的数据类型就是[]
,此时这个变量m就毫无意义了;
1.3 数组的拷贝(深拷贝)
数组只有在数据类型相同的情况下才能进行传递(都是[2]int或者[5]int ……),并且数组是值传递会进行深拷贝,也就是说被赋值的变量地址与赋值的变量不同。
a := [6]int{1,2,3,4,5,6}
x := a
x[0] = 999
fmt.Println(a)
fmt.Println(x)
/*
[1 2 3 4 5 6]
[999 2 3 4 5 6]
*/
2. 切片
2.1 什么是切片及其类型
切片和数组最大的区别就是长度不固定,并且切片的数据类型一定是[]int
。
2.2 切片的拷贝(浅拷贝)
切片最简便的地方就是可以通过x[start:end]来进行一个截取(前闭后开),其中start默认为0,end默认为len(x)。
需要注意的一点是切片是浅拷贝传递因此s2 := s[1:3]
实际上s2中这些数据所存储的空间和s中的这几个元素是相同的,也就是说我改变s2中的值同样也会改变s,反之亦然。
变化的是,s2的下标是重新编排的s[1]对应s2[0],s[2]对应s2[1] (前闭后开因此只有两个)……s2只有两个元素(s[1],s[2])所以他不能够使用s2[2] (越界)。
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5, 6}
b := a[1:3]
b[0] = 999
fmt.Println(a)
fmt.Println(b)
}
/*
[1 999 3 4 5 6]
[999 3]
*/
2.3 切片的追加及深拷贝
package main
import "fmt"
func main() {
a := []int{1, 2, 3}
b := []int{4, 5, 6}
c := make([]int, 0)
a = append(a, b...)
c = append(c, a...)
b[0] = 444
a[0] = 111
fmt.Println(a) // b修改不影响a
fmt.Println(b)
fmt.Println(c) // a修改不影响c
}
/*
[111 2 3 4 5 6]
[444 5 6]
[1 2 3 4 5 6]
*/
由此可见append是直接进行值的传递的。
3. ...
语法糖
3.1 什么是语法糖
以下是维基百科中的解释:
语法糖(英语:Syntactic sugar),指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。
3.2 应用于不定参数
package main
import "fmt"
func main() {
Printer(1, 2, 3)
Printer(4, 5)
}
func Printer(x ...int) {
fmt.Printf("%T\n", x)
for _, v := range x {
fmt.Println(v)
}
}
/*
[]int
1
2
3
[]int
4
5
*/
可以通过上面的测试得知,通过...
语法糖获得的参数组是一个切片类型。
3.3 应用于切片传递
package main
import "fmt"
func main() {
a := []int{1, 2, 3}
b := []int{4}
b = append(b, a[1:3]...)
fmt.Println(a)
fmt.Println(b)
}
/*
[1 2 3]
[4 2 3]
*/
由此可见,...
语法糖多用于切片的操作,它是放在变量名后面的。当需要append多个元素的时候就可以使用该语法糖进行操作。