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

Golang中为何两个切片地址相同但值却不一样?

Go切片底层结构与fmt.Printf("%p")行为解析

切片的底层结构

Go源码中切片的结构体定义为:

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

核心误解纠正

你之前认为s := make([]string, 0)等价于s := &slice{},这是错误的。切片在Go中是值类型,make返回的是slice结构体的实例,而非指向该结构体的指针。

代码现象的具体解析

看你运行的这段代码:

s := make([]int, 0, 2)
s2 := s
s = append(s, 10)
fmt.Printf("%v, %p\n", s, s)
fmt.Printf("%v, %p\n", s2, s2)

出现s和s2打印地址相同但值不同的原因如下:

  • 执行s2 := s时,是对切片结构体做值拷贝,因此s和s2是两个完全独立的slice实例,但它们的array指针指向同一个底层数组。
  • append操作后,s的len字段变为1,而s2的len仍为0,两者的array指针并未改变,依然指向同一数组。
  • fmt.Printf("%p", s)的特殊处理:对于切片类型,%p格式化符不会打印切片结构体自身的内存地址,而是打印其底层数组的起始地址(即s.array的值)。这就是为什么两个独立的切片实例,打印出的地址看起来一致。

你类比的这段代码完全准确,清晰体现了两者的关系:

array := [2]int{10}
s := &slice{
  array: unsafe.Pointer(&array),
  len: 1,
  cap: 2,
}
s2 := &slice{
  array: unsafe.Pointer(&array),
  len: 0,
  cap: 2,
}

s和s2是指向不同slice结构体的指针,但这两个结构体的array指针指向同一个底层数组。如果是普通指针类型,fmt.Printf("%p")会打印指针自身的地址,但切片作为值类型,%p被特殊处理为打印底层数组地址。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:42:56