Go的Slice底层数据结构和特性

Go 的 Slice 底层数据结构和特性

Slice 是 Go 语言中一种动态数组的实现,它提供了比数组更灵活的操作方式。Slice 的底层数据结构是一个结构体,包含指向数组的指针、长度和容量。


1. 底层数据结构

Slice 的底层数据结构是一个包含三个字段的结构体:

  • array:指向底层数组的指针,存储实际的数据。
  • len:当前 Slice 的长度,表示实际存储的元素个数。
  • cap:当前 Slice 的容量,表示底层数组的总大小。

2. 特性

动态扩展
  • 自动扩容:当 Slice 的长度超过容量时,Go 会自动分配一个更大的底层数组,并将原有数据复制到新数组中。
  • 扩容策略:通常,新容量是原容量的两倍,但当容量较大时,扩容因子会减小。
引用类型
  • 共享底层数组:多个 Slice 可以共享同一个底层数组,修改一个 Slice 可能会影响其他 Slice。
  • 浅拷贝:Slice 的赋值和传递是浅拷贝,只复制指针、长度和容量,不复制底层数组。
切片操作
  • 切片表达式 :可以通过切片表达式 s[start:end] 创建一个新的 Slice,新 Slice 共享原 Slice 的底层数组。
  • 容量限制:新 Slice 的容量受原 Slice 的容量限制。

3. 使用场景

动态数组
  • 动态大小:适用于需要动态调整大小的数组场景。
  • 高效操作:支持高效的插入、删除和扩展操作。
数据共享
  • 共享数据:适用于需要共享底层数据的场景,如多个 Slice 共享同一个数组。
高效传递
  • 减少拷贝:由于 Slice 是引用类型,传递 Slice 时不会复制底层数组,适合传递大数据。

Slice 底层数组 长度 len 容量 cap 元素 1 元素 2 ... 元素 n

代码示例
go 复制代码
package main

import "fmt"

func main() {
    // 创建并初始化 Slice
    s := []int{1, 2, 3, 4, 5}
    fmt.Println("Initial Slice:", s) // 输出: Initial Slice: [1 2 3 4 5]
    fmt.Println("Initial Length:", len(s)) // 输出: Initial Length: 5
    fmt.Println("Initial Capacity:", cap(s)) // 输出: Initial Capacity: 5

    // 动态扩展 Slice
    s = append(s, 6, 7, 8)
    fmt.Println("Extended Slice:", s) // 输出: Extended Slice: [1 2 3 4 5 6 7 8]
    fmt.Println("Extended Length:", len(s)) // 输出: Extended Length: 8
    fmt.Println("Extended Capacity:", cap(s)) // 输出: Extended Capacity: 10

    // 共享底层数组
    s1 := s[2:5]
    fmt.Println("Slice s1:", s1) // 输出: Slice s1: [3 4 5]
    fmt.Println("Length of s1:", len(s1)) // 输出: Length of s1: 3
    fmt.Println("Capacity of s1:", cap(s1)) // 输出: Capacity of s1: 8

    // 修改 s1 会影响原 Slice s
    s1[0] = 99
    fmt.Println("Modified Slice s:", s) // 输出: Modified Slice s: [1 2 99 4 5 6 7 8]
    fmt.Println("Modified Slice s1:", s1) // 输出: Modified Slice s1: [99 4 5]

    // 切片操作
    s2 := s[:3]
    fmt.Println("Slice s2:", s2) // 输出: Slice s2: [1 2 99]
    fmt.Println("Length of s2:", len(s2)) // 输出: Length of s2: 3
    fmt.Println("Capacity of s2:", cap(s2)) // 输出: Capacity of s2: 10
}
相关推荐
飘尘1 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
浏览器工程师2 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
行者全栈架构师2 小时前
Maven dependency:tree 的 8 个高级用法
java·后端
Chenyiax2 小时前
从一次请求看懂 OkHttp:架构、调度与连接管理
后端
爱勇宝3 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
AskHarries3 小时前
工具失败时怎么办:重试、回滚、人工确认和风险提示
后端·程序员
苏三说技术5 小时前
Claude Code从失控到起飞,只用了这些技巧
后端
长栎6 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode6 小时前
Redis 在生产项目的使用
前端·后端
用户559822481226 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端