golang中切边和数组

golang中数组array是具有相同唯一类型 的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型,切片slice其实是数组array的一种抽象。

数组array

数组arrays很好理解,就是一个固定长度、固定元素类型的数组。在go中数组类型包含两层意思:长度和元素类型。

定义

var a [2]int 
var b [3]int 
  • 数组不需要主动的进行初始化,相对应的0值会在声明后被赋值。在内存中[2]int就是线性排列的2个int值,所以数组访问是O(1)的时间复杂度,速度极快。
  • 数组arrays在go中是值,而不是指针

初始化

初始化声明一般有两种。e这种声明不用填长度,编译器会帮你计算这个数。

d := [2]int{11, 22} 
e := [...]int{11, 22} 
fmt.Println(d == e)  // 输出 true

切片slice

切片(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} // 切片类型 

创建和初始化

通过 make() 函数创建切片
// 创建一个整型切片
// 其长度和容量都是 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}
slice切片和数组的区分

当使用字面量来声明切片时,其语法与使用字面量声明数组非常相似。二者的区别是:如果在 [] 运算符里指定了一个值,那么创建的就是数组而不是切片。只有在 [] 中不指定值的时候,创建的才是切片。

nil 和空切片

有时,程序可能需要声明一个值为 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
golang map扩容
golang 变长参数
标签:

发表我的评论

电子邮件地址不会被公开。 必填项已用*标注

87 + 67 =

ajax-loader