golang中的append函数详解

lijingtian · · 15995 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

15995 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传