Golang语言中切片的长度和容量的概念和使用

 更新时间:2025年11月02日 09:45:55   作者:学亮编程手记  
这篇文章主要介绍了Golang语言中切片的长度和容量的概念和使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

本文我们来详细讲解 Go 语言中切片(Slice)的长度(Length)容量(Capacity)。这是理解切片工作原理的核心概念。

核心概念

  1. 长度(Length):

    • 表示切片当前实际包含的元素个数
    • 通过内置函数 len(slice) 获取。
    • 访问切片中索引 >= len(slice) 的元素会引发“索引越界”的运行时恐慌(panic)。
  2. 容量(Capacity):

    • 表示切片底层数组(Underlying Array)从切片的起始位置到数组末尾的元素个数
    • 它代表了切片在不分配新内存的情况下,可以增长的最大限度。
    • 通过内置函数 cap(slice) 获取。

底层数组(Underlying Array)

切片是一个轻量级的数据结构,它提供了对底层数组一个连续片段的引用。它包含三个组件:

  • 指针:指向底层数组中切片起始位置的元素。
  • 长度:切片中元素的数量。
  • 容量:从切片起始位置到底层数组末尾的元素数量。

这个概念是理解长度和容量区别的关键。

图示与示例

让我们通过一个例子和图示来理解。

// 1. 创建一个底层数组
arr := [5]int{10, 20, 30, 40, 50} // 数组,长度和容量固定为5

// 2. 基于数组创建一个切片
// slice 从 arr[1] 开始,到 arr[3] 结束 (不包括 arr[4])
slice := arr[1:4] // [20, 30, 40]

此时的内存布局可以这样表示:

底层数组: [10, 20, 30, 40, 50]
索引:      0   1   2   3   4
              ^         ^
              |         |
           slice起始   slice结束 (不包括索引4)
           slice指针指向这里
  • len(slice):切片包含了 arr[1], arr[2], arr[3] 这三个元素,所以 长度为 3。
  • cap(slice):切片的指针从 arr[1] 开始,底层数组的末尾是 arr[4],所以从起始位置到末尾有 arr[1], arr[2], arr[3], arr[4] 这 4个位置,因此 容量为 4。
fmt.Println(slice)      // 输出: [20 30 40]
fmt.Println(len(slice)) // 输出: 3
fmt.Println(cap(slice)) // 输出: 4

容量是如何被使用的:append 函数

当你使用 append 函数向切片追加新元素时,Go 运行时会检查容量是否足够。

  1. 容量足够时
    新元素会被直接放入底层数组切片末尾之后的空间,长度增加,容量不变。

    newSlice := append(slice, 60) // 追加元素 60
    fmt.Println(newSlice)          // 输出: [20 30 40 60]
    fmt.Println(len(newSlice))     // 输出: 4
    fmt.Println(cap(newSlice))     // 输出: 4 (容量刚好够用,没有分配新数组)
    fmt.Println(arr)               // 输出: [10 20 30 40 60] (原数组被修改了!)
    
  2. 容量不足时
    Go 运行时会创建一个新的、更大的底层数组(通常是当前容量的 2 倍,但对于较小的切片,增长策略可能不同),将原有元素复制到新数组中,然后追加新元素。此时的切片引用的是一个全新的数组,与原数组无关

    newSlice2 := append(newSlice, 70, 80) // 追加两个元素,超出当前容量4
    fmt.Println(newSlice2)                 // 输出: [20 30 40 60 70 80]
    fmt.Println(len(newSlice2))            // 输出: 6
    fmt.Println(cap(newSlice2))            // 输出: 8 (新数组的容量,通常是旧容量的2倍)
    fmt.Println(arr)                       // 输出: [10 20 30 40 60] (原数组未受影响)
    

使用make创建切片时指定长度和容量

你可以使用 make 函数在创建切片时直接指定其初始长度和容量。

语法:make([]T, length, capacity)

// 创建一个切片,长度为3(前3个元素被初始化为零值),容量为5
s := make([]int, 3, 5)
fmt.Println(s)          // 输出: [0 0 0]
fmt.Println(len(s))     // 输出: 3
fmt.Println(cap(s))     // 输出: 5

// 你可以安全地访问和修改 s[0], s[1], s[2]
// 你可以追加最多2个新元素(5-3=2)而不会触发重新分配
s = append(s, 1)
fmt.Println(s)          // 输出: [0 0 0 1]
fmt.Println(len(s))     // 输出: 4

如果省略容量参数,则容量默认与长度相等。

s2 := make([]int, 3) // len=3, cap=3
fmt.Println(s2, len(s2), cap(s2)) // 输出: [0 0 0] 3 3

总结与要点

特性长度 (len)容量 (cap)
含义当前元素个数可增长的最大限度
函数len(s)cap(s)
动态性随 append/slice 操作变化在触发扩容前不变
用途决定可访问的元素范围影响性能(减少内存分配和复制)
  • 切片是引用类型。多个切片可以共享同一个底层数组。修改一个切片的元素可能会影响其他共享底层数组的切片。
  • “扩容”是一个相对昂贵的操作,涉及内存分配和数据复制。在能预估所需数据量的情况下,使用 make([]T, 0, capacity) 预先分配一个足够大的容量是提升性能的有效手段。
  • 对切片进行重新切片(reslicing,如 s2 := s1[1:3])操作时,新切片会和原切片共享底层数组。新切片的长度和容量会基于新的起始索引重新计算。

理解长度和容量的区别,能帮助你更好地使用切片,写出更高效、更可靠的 Go 代码。

到此这篇关于Golang语言中切片的长度和容量的概念和使用的文章就介绍到这了,更多相关Golang 切片的长度和容量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go语言中strings和strconv包示例代码详解

    Go语言中strings和strconv包示例代码详解

    这篇文章主要介绍了Go语言中strings和strconv包示例代码详解 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-11-11
  • 浅析Golang中rune类型的使用

    浅析Golang中rune类型的使用

    从golang源码中看出,rune关键字是int32的别名(-231~231-1),对比byte(-128~127),可表示的字符更多,本文就来简单聊聊它的使用方法吧,希望对大家有所帮助
    2023-05-05
  • go语言-在mac下brew升级golang

    go语言-在mac下brew升级golang

    这篇文章主要介绍了go语言-在mac下brew升级golang,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang 字符串转time类型实现

    Golang 字符串转time类型实现

    本文主要介绍了Golang 字符串转time类型实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Go基于struct tag实现结构体字段级别的访问控制

    Go基于struct tag实现结构体字段级别的访问控制

    本文将会基于这个主题展开,讨论Go中的结构体tag究竟是什么,我们该如何利用它,另外,文末还提供了一个实际案例,实现结构体字段级别的访问,帮助我们进一步提升对struct tag的理解
    2024-02-02
  • Golang 经典校验库 validator 用法解析

    Golang 经典校验库 validator 用法解析

    这篇文章主要为大家介绍了Golang 经典校验库 validator 用法解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Go prometheus metrics条目自动回收与清理方法

    Go prometheus metrics条目自动回收与清理方法

    这篇文章主要为大家介绍了Go prometheus metrics条目自动回收与清理方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Go实现SSE消息推送的项目实战

    Go实现SSE消息推送的项目实战

    本文主要介绍了Go实现SSE消息推送的项目实战,结合JavaScript前端集成,构建实时数据推送系统,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2025-05-05
  • go语言操作之nacos配置中心

    go语言操作之nacos配置中心

    这篇文章主要介绍了go语言操作之nacos配置中心,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • go语言中使用ent做关联查询的示例详解

    go语言中使用ent做关联查询的示例详解

    go语言的ent框架是facebook开源的ORM框架,是go语言开发中的常用框架,而关联查询又是日常开发中的常见数据库操作,故文本给出一个使用ent做关联查询的使用示例,需要的朋友可以参考下
    2024-02-02

最新评论