func main() {
var a = []int{1, 2, 3, 4, 5}
b := a //此时a,b都指向了内存中的[1 2 3 4 5]的地址
b[1] = 10 //相当于修改同一个内存地址,所以a的值也会改变
c := make([]int, 5, 5) //切片的初始化
copy(c, a) //将切片acopy到c
c[1] = 52 //copy是值类型,所以a不会改变c
fmt.Println(a, c) // [1 10 3 4 5] [1 52 3 4 5]
d := &a //将a的内存地址赋值给d,取值用*d
a[1] = 11
fmt.Printf("d的值是%v,d的内存地址是%p\n", *d, d) //d的值是[1 11 3 4 5],d的内存地址是0xc420084060
fmt.Printf("a的值是%v,a的内存地址是%p\n", a, &a) //a的值是[1 11 3 4 5],a的内存地址是0xc420084060
fmt.Printf("b的值是%v,b的内存地址是%p\n", b, &b) //b的值是[1 11 3 4 5],b的内存地址是0xc000008060
}
对于上面代码中,a,b都指向了内存中的[1 2 3 4 5]的地址,为啥&a和&b不一样呢?
d却和a的指针一样?
关键概念区分
这里涉及到两个不同的地址:
- 切片变量本身的地址(&a、&b)
- 切片底层数组的地址(切片内部指向的数据)
图解说明:

具体解释:
第3行:b := a
- a 和 b 是两个独立的切片变量(切片头),它们在栈上有不同的内存地址
- 但它们内部的指针字段指向同一个底层数组 [1, 2, 3, 4, 5]
- 所以 &a != &b(切片变量本身的地址不同)
- 但修改 b[1] 会影响 a,因为它们共享底层数组
第9行:d := &a
- d 是一个指向切片 a 的指针(类型是 *[]int)
- d 存储的是 a 变量的地址,所以 d == &a
- *d 解引用后得到的就是 a 这个切片
总结

核心要点
- &a 和 &b 不同,因为它们是两个不同的变量
- d == &a,因为 d 就是被赋值为 &a 的
- a 和 b 共享底层数组,是因为它们的内部指针字段相同,而不是因为它们本身的地址相同
- 这就是为什么Go的切片是引用语义:赋值时复制的是切片头(包含指针、长度、容量),但指针指向的是同一块底层数据。