Golang Slice 的底层实现

发布于 1周前 作者 yuanlaile 最后一次编辑是 5天前 来自 问答

Golang Slice 的底层实现

切片是基于数组实现的,它的底层是数组,它自己本身非常小,可以理解为对 底层数组的抽象。因为基于数组实现,所以它的底层的内存是连续分配的,效 率非常高,还可以通过索引获得数据。

切片本身并不是动态数组或者数组指针。它内部实现的数据结构通过指针引用 底层数组,设定相关属性将数据读写操作限定在指定的区域内。切片本身是一 个只读对象,其工作机制类似数组指针的一种封装。

切片对象非常小,是因为它是只有 3 个字段的数据结构: 指向底层数组的指针 切片的长度 切片的容量

1 回复

在Go语言中,Slice(切片)是一个非常重要的数据结构,它提供了一种灵活的方式来处理序列化的数据集合。Slice 的底层实现是基于数组的,但它比数组更加灵活,因为切片可以动态地增长和缩小。Slice 的结构实际上包含了三个主要部分:指向数组的指针、切片的长度(length),以及切片的容量(capacity)。

Slice 的底层结构

在Go的底层实现中,Slice 可以通过一个结构体来表示,但Go语言本身并不直接暴露这个结构体的定义。不过,我们可以这样理解它的结构:

type SliceHeader struct {
    Data uintptr // 指向数组的指针
    Len  int     // 切片的长度
    Cap  int     // 切片的容量
}

// 注意:这只是一个示例性的表示,实际的Slice并不是这样定义的

示例代码

虽然我们不能直接操作Slice的底层结构(因为SliceHeader不是标准库的一部分),但可以通过一些Go语言的特性来间接展示Slice的行为:

package main

import (
    "fmt"
)

func main() {
    // 创建一个切片
    s := make([]int, 0, 5) // 长度0,容量5

    // 添加元素
    s = append(s, 1, 2, 3)

    fmt.Println("Length:", len(s), "Capacity:", cap(s)) // 长度3,容量5

    // 扩容
    s = append(s, 4, 5, 6)

    fmt.Println("Length after append:", len(s), "Capacity after append:", cap(s)) // 可能长度6,容量变化(取决于运行时)

    // 切片操作
    subSlice := s[1:4] // 截取s中的一部分

    fmt.Println("SubSlice:", subSlice) // 输出:[2 3 4]

    // 修改子切片元素会影响原切片
    subSlice[1] = 99
    fmt.Println("Modified Original Slice:", s) // 输出:[1 99 4 5 6],说明切片是引用传递
}

结论

Go的Slice是一个非常强大的数据结构,它提供了灵活的方式来处理集合数据,同时保持了对底层数组的引用,从而实现了高效的内存使用和数据操作。虽然我们不能直接操作Slice的底层SliceHeader结构,但了解其背后的原理对于编写高效、可维护的Go代码至关重要。

回到顶部