You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言结构体中切片的内存存储及与指针切片的差异解析

Go结构体中切片与切片指针的内存解析

一、结构体字段为切片时的内存存储

Go语言里的切片本质是一个包含三个字段的内部结构体:

  • 指向底层数组的指针
  • 切片的长度(len)
  • 切片的容量(cap)

当你定义type deque struct { indexes []int }并初始化实例dq后,adr(dq)=0x1001这个地址对应的内存区域,存储的是整个deque结构体的内容。其中indexes字段占据的内存空间,就是上述切片的三个字段:

  • 0x1001开始的前8字节(64位系统):存储指向底层数组的指针(比如你说的0x8009)
  • 接下来8字节:存储切片当前的长度
  • 再接下来8字节:存储切片当前的容量

它既不是直接存储数组本身,也不是只存一个数组指针,而是完整存储切片的三个核心属性。

二、执行d.indexes = append(d.indexes, i)的过程

append函数的执行逻辑分两种情况:

  1. 容量足够:如果当前切片的容量cap大于等于len+1,直接在底层数组的len位置写入新元素i,然后将切片的长度len加1,返回原切片的引用,最后把d.indexes更新为这个长度增加后的切片。
  2. 容量不足:Go会自动分配一块新的、更大的内存作为新的底层数组(通常是原容量的2倍,小容量时可能按倍数增长,大容量时增长比例降低),把原底层数组的所有元素拷贝到新数组中,再写入新元素i,然后返回一个指向新数组的新切片,最后将d.indexes替换为这个新切片。

因为d是指向deque实例的指针,所以对d.indexes的修改会直接作用于原结构体实例。

三、改为indexes *[]int的差异

当结构体定义为type deque struct { indexes *[]int }时,和原版本的核心差异如下:

  1. 内存存储不同:此时adr(dq)=0x1001存储的deque结构体中,indexes字段是一个指针(8字节,64位系统),这个指针指向另一个内存地址(比如0x2000),而0x2000地址才是存储切片三个字段(数组指针、len、cap)的地方。
  2. 初始化与操作风险:使用时必须先初始化切片并将指针指向它,比如dq.indexes = &[]int{},否则indexes是nil指针,直接调用append会触发panic。而原版本的切片字段默认是nil切片,可以直接调用append(会自动分配底层数组)。
  3. 拷贝与修改行为:
    • 拷贝deque实例时,原版本拷贝的是切片的三个字段,拷贝后的实例和原实例共享底层数组,但各自的切片字段是独立的(修改其中一个的len/cap不会影响另一个,除非修改底层数组元素);
    • 新版本拷贝的是切片指针,拷贝后的实例和原实例指向同一个切片结构体,修改任意一个的切片属性(len/cap、底层数组指针)都会直接影响另一个。
  4. append的写法:新版本需要通过解引用指针来操作切片,比如*dq.indexes = append(*dq.indexes, i),如果错误写成dq.indexes = &append(*dq.indexes, i),虽然语法合法,但完全没必要,还会额外创建切片指针的副本。

内容的提问来源于stack exchange,提问作者Tian Gao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:52:40