文章目录
golang中数组array是具有相同唯一类型 的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型,切片slice其实是数组array的一种抽象。
数组arrays很好理解,就是一个固定长度、固定元素类型的数组。在go中数组类型包含两层意思:长度和元素类型。
var a [2]int
var b [3]int
初始化声明一般有两种。e这种声明不用填长度,编译器会帮你计算这个数。
d := [2]int{11, 22}
e := [...]int{11, 22}
fmt.Println(d == e) // 输出 true
切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合。切片是围绕动态数组的概念构建的,可以按需自动增长和缩小。切片的动态增长是通过内置函数 append() 来实现的,这个函数可以快速且高效地增长切片,也可以通过对切片再次切割,缩小一个切片的大小。
底层数据结构定义:
// src/runtime/slice.go
type slice struct {
array unsafe.Pointer
len int
cap int
}
[]T就是一个切片slices,和声明数组的区别就是没有指定长度。
d := [2]int{11, 22} // 数组类型
s1 := []int{11, 22, 33} // 切片类型
// 创建一个整型切片
// 其长度和容量都是 5 个元素
slice := make([]int, 5)
//此时只指定了切片的长度,那么切片的容量和长度相等。也可以分别指定长度和容量:
// 创建一个整型切片
// 其长度为 3 个元素,容量为 5 个元素
slice := make([]int, 3, 5)
另一种常用的创建切片的方法是使用切片字面量,这种方法和创建数组类似,只是不需要指定[]运算符里的值。初始的长度和容量会基于初始化时提供的元素的个数确定:
// 创建字符串切片
// 其长度和容量都是 3 个元素
myStr := []string{"Jack", "Mark", "Nick"}
// 创建一个整型切片
// 其长度和容量都是 4 个元素
myNum := []int{10, 20, 30, 40}
当使用字面量来声明切片时,其语法与使用字面量声明数组非常相似。二者的区别是:如果在 [] 运算符里指定了一个值,那么创建的就是数组而不是切片。只有在 [] 中不指定值的时候,创建的才是切片。
有时,程序可能需要声明一个值为 nil 的切片(也称nil切片)。只要在声明时不做任何初始化,就会创建一个 nil 切片
// 创建 nil 整型切片
var myNum []int
空切片和 nil 切片稍有不同,下面的代码分别通过 make() 函数和字面量的方式创建空切片:
// 使用 make 创建空的整型切片
myNum := make([]int, 0)
// 使用切片字面量创建空的整型切片
myNum := []int{}
空切片的底层数组中包含 0 个元素,也没有分配任何存储空间。想表示空集合时空切片很有用,
切片之所以被称为切片,是因为创建一个新的切片,也就是把底层数组切出一部分。通过切片创建新切片的语法如下:
slice[i:j]
slice[i:j:k]
需要注意的是:现在两个切片 myNum 和 newNum 共享同一个底层数组。如果一个切片修改了该底层数组的共享
// 修改 newNum 索引为 1 的元素
// 同时也修改了原切片 myNum 的索引为 2 的元素
newNum[1] = 35
函数 append() 会智能地处理底层数组的容量增长。在切片的容量小于 1024 个元素时,总是会成倍地增加容量。一旦元素个数超过 1024,容量的增长因子会设为 1.25,也就是会每次增加 25%的容量(随着语言的演化,这种增长算法可能会有所改变)。
// src/runtime/slice.go
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
myNum := []int{10, 20, 30, 40, 50}
// 迭代每一个元素,并显示其值
for index, value := range myNum {
fmt.Printf("index: %d value: %d\n", index, value)
}
Golang 内置的 copy() 函数可以将一个切片中的元素拷贝到另一个切片中,其函数声明为:
func copy(dst, src []Type) int