Golang:切片的底层详解和初步使用

金刀大菜牙 · · 760 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

什么是切片

切片是 Golang 中比较特殊的数据结构,这种数据结构更便于使用和管理数据集合。简单的说,切片就是一种简化版的动态数组。因为动态数组的长度不固定,所以切片的长度自然也就不能是类型的组成部分了。切片是围绕动态数组的概念构建的,是对数组的抽象。数组虽然有适用的地方,但是数组的类型和操作都不够灵活,因此在 Go 代码中数组使用的并不是很多,而切片则使用的相当广泛,理解切片的原理和用法相当重要。

切片的内部结构

我们先来看看切片的结构定义,即 reflect.SliceHeader:

type SliceHeader struct {
    Data unitptr
    Len int
    Cap int
}

由切片的结构定义可知,切片的结构由三个信息组成:

  1. 指针,指向底层数组中切片指定的开始位置

  2. 长度,即切片的长度

  3. 最大长度,也就是切片开始位置到数组的最后位置的长度

下图给出了切片 x := [2, 3, 5, 7, 9, 11, 13, 15] 和 y := [1:3] 两个切片对应的内存结构。

切片底层结构图.png

切片的创建和初始化

让我们看看切片有哪些创建和初始化的方式:

var(
  a []int // nil 切片,和 nil 相等,一般用来表示一个不存在的切片
  b = []int{} // 空切片,和 nil 不相等,一般用来表示一个空的集合  
  c = []int{1, 2, 3, 4} // 有 4 个元素的切片,len 和 cap 都为 4
  d = c[:2] // 有 2 个元素的切片,len 为 2,cap 为 4
  e = c[0:2:cap(c)] // 有 2 个元素的切片,len 为 2,cap 为 4
  f = c[:0] // 有 0 个元素的切片,len 为 0,cap 为 4
  g = make([]int, 3) // 有 3 个元素的切片,len 和 cap 都为 3
  h = make([]int, 3, 5) // 有 3 个元素的切片,len 为 3,cap 为 5
  i = make([]int, 0, 5) // 有 0 个元素的切片,len 为 0,cap 为 5
)

使用 Golang 内置的函数 len() 可以查看切片中有效元素的长度,内置的函数 cap() 可以查看切片容量大小。

QQ截图20200924233835.png

修改切片

切片没有自己的任何数据,它只是底层数组的一个表示。对切片所做的任何修改都将反映在底层数组中。

示例代码:

package main

import (  
    "fmt"
)

func main() {  
    darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
    dslice := darr[2:5]
    fmt.Println("array before",darr)
    for i := range dslice {
        dslice[i]++
    }
    fmt.Println("array after",darr) 
}

运行结果:

array before [57 89 90 82 100 78 67 69 59]  
array after [57 89 91 83 101 78 67 69 59] 

当多个片共享相同的底层数组时,每个元素所做的更改将在数组中反映出来。

示例代码:

package main

import (  
    "fmt"
)

func main() {  
    numa := [3]int{78, 79 ,80}
    nums1 := numa[:] //creates a slice which contains all elements of the array
    nums2 := numa[:]
    fmt.Println("array before change 1",numa)
    nums1[0] = 100
    fmt.Println("array after modification to slice nums1", numa)
    nums2[1] = 101
    fmt.Println("array after modification to slice nums2", numa)
}

运行结果:

array before change 1 [78 79 80]  
array after modification to slice nums1 [100 79 80]  
array after modification to slice nums2 [100 101 80]

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:金刀大菜牙

查看原文:Golang:切片的底层详解和初步使用

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

760 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传