美文网首页
Golang笔记(一):数组与切片

Golang笔记(一):数组与切片

作者: MaxHere | 来源:发表于2018-02-03 00:51 被阅读0次

数组

  • 创建方式:
    以创建 int 类型数组为例
var array1 [3]int // 元素会被自动初始化为0值 => {0, 0, 0}
array2 := [3]int{1} // 位提供初始化的元素被初始化为零值 => {1, 0, 0}
arary3 := [3]int{1, 2: 3} // 指定索引2的元素初始化值为3 => {1, 0, 3}
array4 := [...]int{1, 2, 3} // 不直接指定长度,编译器会根据元素个数给定长度 => {1, 2, 3}
array5 := [...]int{1, 2: 3} // 指定索引 2 的元素初始化值为3,会影响该数组长度 => {1, 0, 3}
  • 复合型数组:
    复合型数组可以省略类型化标签
type Student struct {
    name string 
    age    int 
}
studentArray := [...]Student {
    {"studentA", 18}, // 省略结构体标签
    {"studentB", 20}
}
  • 多维数组
    注意: 1. 多维数组仅允许第一维使用 ...
    2. 内置函数 len 和 cap 都只返回第一维数组的长度

  • 比较
    如果元素支持 == 比较,那么该数组也支持此操作

切片

切片本身是个只读对象,其工作机制累死数组指针的一种包装。可以基于数组或数组指针创建切片,以开始和结束索引位置确定引用的数组片段。不支持反向索引,世纪范围是一个右半开区间。属性 cap 表示切片所引用数组片段的真是长度,len 用于限定可读的写元素数量。另外,数组必须 addressable,否则会引发错误。
与数组区别:

  1. 切片创建不需要提前声明长度;而数组需要声明,操作数组索引大于该数组长度,会产生越界的异常。
  2. 切片可以通过 make([]int, 3, 5) 方式创建,第一个参数为类型,第二个参数为长度(len),第三个参数为容量(cap)
  3. 切片的长度(len)和 容量(cap)两个属性不一定相等;而数组的两个属性一定相等。切片底层是数组的一部分或者全部, cap 值为从切片引用该底层数组开头部分到该底层数组结尾的长度,而 len 值为该切片引用的底层数组部分的长度。
  4. 切片是引用类型,而数组是值类型。说白了就是切片传递的是引用,只要对任意一个地方修改原切片值也会改变;而数组是值类型,每次传递相当于重新分配内存创建了一个新的数组,各个之间相互独立不影响。
  5. 切片不支持比较操作,即使元素类型支持也不行,仅可以判断您是否是 nil
  • 创建方式:
sliceA := make([]int, 2, 5)  // len = 2 cap = 5 => {0, 0}
sliceB := make([]int2, 2]) // len = 2 cap = 5 => {0, 0}
sliceC := []int{1, 2, 3, 5: 30} // len = 6 cap = 6 => {1, 2, 3, 0, 0, 30}

注意:
下面两种声明方式,前者只是定义了一个 []int 类型变量,并未执行初始化操作;而后者则用初始化表达式完成了全部创建过程。

var sliceA []int // sliceA == nil true
sliceB := []int{} // sliceB == nil false
  • 优势
  1. 很显然,切片只是很小的结构体对象,用来代替数组传参可以避免复制开销
  2. make 函数允许在运行期动态制定数组长度,绕开了数组类型必须使用编译期常量的限制。

然而,并非所有时候都适合使用切片代替数组,因为切片底层数组可能会在堆上分配内存, 而且小数组在栈上拷贝的消耗也未必就比 make 代价大。

  • append
    向切片尾部添加数据(slice[len]),返回新的切片对象(如果超过 cap 限制,则为心切片独享重新分配内存和数组,所以要返回新的切片对象)。向 nil 切片追加数据时,会为其分配底层数组内存。
slice := make([]int, 0, 5) // {}
sliceA := append(slice, 10) // {10,}
sliceB := append(sliceB, 20, 30) // {10, 20, 30}
sliceC := append(sliceB, 100, 200, 300) // {10, 20, 30, 100, 200, 300} => 超出 cap, 新切片的地址已经变了

注意:

  • 是超出切片 cap 限制,而非超出底层数组长度限制,因为 cap 可小于数组长度。
  • 新分配数组长度是原 cap 的 2 倍,而非原数组的 2 倍(并非总是 2 倍,对于较大的切片,会尝试扩容 1/4,以节约内存)
  • 因为存在重新分配底层数组的缘故,建议预留足够空间,避免多次分配复制的内存开销
  • copy
    在两个切片对象间复制数据,允许指向同一底层数组,允许目标区间重叠。最终所复制长度以较短的切片长度(len)为准。
slice := []int{1, 2, 3, 4, 5}
sliceA := slice[:] // {1, 2, 3, 4, 5}
sliceB := slice[1:3] // {2, 3}
n:= copy(sliceA, sliceB) //sliceA:{2 3 3 4 5} sliceB:{3, 3} n: 2

注意

  • 如果切片长时间引用大数组中很小的片段,建议新建独立切片,复制出所需数据,以便于原数组内存被及时回收。

相关文章

  • Golang数组与切片

    Golang数组与切片 数组的声明 Golang中的数组属于静态数组,不允许动态扩展 Golang中数组会默认初始...

  • Golang笔记(一):数组与切片

    数组 创建方式:以创建 int 类型数组为例 复合型数组:复合型数组可以省略类型化标签 多维数组注意: 1. 多...

  • 数组与切片-GOLANG

    golang -@amazeUI -2017-08-02 14:19:14 a := [10]int{1, 2, ...

  • golang 数组与切片

    1. 切片与数组对比 (1). 列表数组是具有固定长度且拥有零个或者多个相同数据类型元素的序列。数组的长度是数组类...

  • 数组与切片 golang

    b 等于 a 的第四个元素到最后一个元素。这是取数组的一部分出来,也可以写作 a[5:],a[5:len(a)],...

  • golang核心编程

    golang核心笔记 Go的编译命令 变量 slice切片:是对数组一个连续片段的引用,是一种引用类型 切片提供了...

  • 一篇文章理解 golang 中切片与数组的关系

    起始 在 golang 文档中,对数组与切片有一些详细的讲解,本文主要讲解数组与切片的关系 由于是个人理解,可能有...

  • Golang:数组与切片的复制

    在Golang中,数组是值类型而切片是引用类型。因此值的复制与切片的复制并不相同。 数组的复制 对于值类型的数组来...

  • 简记python的tuple和slice

    python也有类似于golang中数组和切片的概念。python中的数组为tuple(固定的),切片为list(...

  • Golang 数组 切片

    Golang 数组和切片 go提供了相应数据类型来存储多个相同类型的元素。它们分别是数组和slice切片。其中,切...

网友评论

      本文标题:Golang笔记(一):数组与切片

      本文链接:https://www.haomeiwen.com/subject/bnoezxtx.html