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

Golang中操作赋值得到的slice为何会修改原切片的底层数据?

Go切片操作修改原切片的底层逻辑解释

核心前提:Go切片的底层结构

  • Go的切片本质是一个三元结构体,包含三个字段:
    • 指向底层数组的指针*T
    • 切片当前长度len
    • 切片最大容量cap
  • 我们平时对切片的赋值操作(比如b := a),只是拷贝这个切片结构体本身,不会拷贝底层数组,所以赋值后a和b指向同一块底层数组内存。

代码逐行拆解

先列出示例代码方便对照:

func main() {
    a := []int{1,2,3,4}
    b := a
    b = append(b[0:1], b[2:]...)
    fmt.Println(b)
    fmt.Println(a)
}
  1. 初始化a := []int{1,2,3,4}:a的len=4,cap=4,底层数组为[1,2,3,4]
  2. b := a:拷贝切片结构体给b,此时b的len=4、cap=4,和a指向同一个底层数组
  3. 执行append(b[0:1], b[2:]...):
    • 首先b[0:1]是切片截取操作,未指定第三个容量参数时,新切片的容量=原切片容量-起始索引,所以b[0:1]的len=1,cap=4,底层数组还是原来的那块
    • 此时append需要追加2个元素(b[2:]是[3,4]),1+2=3 ≤ cap=4,不会触发扩容,直接在原底层数组上修改:从索引1的位置开始写入3、4
    • 原底层数组会从[1,2,3,4]被修改为[1,3,4,4](索引3的4没有被覆盖)
    • append返回的新切片赋值给b,此时b的len更新为3,cap还是4
  4. 打印结果:
    • b的len是3,所以输出[1,3,4]
    • a的结构体没有被修改,len还是4,会读取底层数组全部4个元素,所以输出[1,3,4,4]

误区说明

你以为b := a是值传递就不会影响原切片的认知是对的,切片赋值确实是值传递,但传递的是切片结构体本身,结构体里的指针还是指向同一块底层数组,只要append没有触发扩容,对底层数组的写入就会同步反映到所有指向该数组的切片上。如果append时需要的总长度超过切片容量,Go会新分配一块更大的底层数组,把旧数据拷贝过去,此时修改才不会影响原来的切片。

内容的提问来源于stack exchange,提问作者Say.My.Name.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:48:00