1. append函数是用来在slice末尾追加一个或者多个元素。
2. 当追加元素时,发现slice的**len>cap**时,会重新开辟一个**2*cap**的内存空间去存储追加过元素的slice。
3. 如果追加元素后slice的**len<=cap**,则append返回的新生成的slice的内存地址**依旧**是传入的slice参数的内存地址。
```go
testSlice := make([]int, 0)
testSlice = append(testSlice, 0)
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice), cap(testSlice), testSlice)
//len: 1, cap: 1, data:[0]
fmt.Printf("testSlice地址:%p \n", &testSlice[0])
//testSlice地址:0xc04203c1d0
testSlice = append(testSlice, 1)
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice), cap(testSlice), testSlice)
//len: 2, cap: 2, data:[0 1]
//因为cap长度不够,所以重新申请一个2*cap长度的内存空间,将内容拷贝到2倍cap的内存中
fmt.Printf("testSlice地址:%p \n", &testSlice[0])
//testSlice地址:0xc04203c220
//testSlice的内存地址变化了
testSlice = append(testSlice, 2)
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice), cap(testSlice), testSlice)
//len: 3, cap: 4, data:[0 1 2]
fmt.Printf("testSlice地址:%p \n", &testSlice[0])
//testSlice地址:0xc042042480
testSlice = append(testSlice, 3)
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice), cap(testSlice), testSlice)
//len: 4, cap: 4, data:[0 1 2 3]
fmt.Printf("testSlice地址:%p \n", &testSlice[0])
//testSlice地址:0xc042042480
//因为cap空间足够用,所以继续在原来的内存地址上追加数据
testSlice1 := append(testSlice, 4)
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice), cap(testSlice), testSlice)
//len: 4, cap: 4, data:[0 1 2 3]
fmt.Printf("testSlice地址:%p \n", &testSlice[0])
//testSlice地址:0xc042042480
//testSlice的数据不变
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice1), cap(testSlice1), testSlice1)
//len: 5, cap: 8, data:[0 1 2 3 4]
fmt.Printf("testSlice1地址:%p \n", &testSlice1[0])
//testSlice1地址:0xc0420440c0
//新生成的testSlice1内存地址变化了
testSlice2 := append(testSlice1, 5)
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice1), cap(testSlice1), testSlice1)
//len: 5, cap: 8, data:[0 1 2 3 4]
fmt.Printf("testSlice1地址:%p \n", &testSlice1[0])
//testSlice1地址:0xc0420440c0
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice2), cap(testSlice2), testSlice2)
//len: 6, cap: 8, data:[0 1 2 3 4 5]
fmt.Printf("testSlice2地址:%p \n", &testSlice2[0])
//testSlice2地址:0xc0420440c0
//在这里可以看到testSlice1和testSlice2的内存地址是一样的
p := unsafe.Pointer(&testSlice1[4])
q := uintptr(p) + 8
t := (*int)(unsafe.Pointer(q))
fmt.Println("testSlice1可以拿到testSlice2的第五个元素值:", *t)
//testSlice1可以拿到testSlice2的第五个元素值: 5
testSlice2[0] = 99999
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice1), cap(testSlice1), testSlice1)
//len: 5, cap: 8, data:[99999 1 2 3 4]
fmt.Printf("testSlice1地址:%p \n", &testSlice1[0])
//testSlice1地址:0xc0420440c0
fmt.Printf("len: %d, cap: %d, data:%+v \n", len(testSlice2), cap(testSlice2), testSlice2)
//len: 6, cap: 8, data:[99999 1 2 3 4 5]
fmt.Printf("testSlice2地址:%p \n", &testSlice2[0])
//testSlice2地址:0xc0420440c0
//修改testSlice2的值同时会改变testSlice1中的值
//当然testSlice1一般不能访问testSlice2中的第6个元素,因为testSlice1的len是5
//但是可以通过上面的方法访问,通过操作内存地址来访问
```
---
参考网址:
https://studygolang.com/articles/10924
有疑问加站长微信联系(非本文作者))