golang切片slice

news/2024/11/28 4:35:39/

切片不是数组,他是指向底层的数组
创建一般用make方法,第一个参数是指向的数组类型,第二个是存放元素的个数,第三个是存放容量,如果存放的个数超过容量,那么他就会从分配内存地址(容量在原来的基础上*2),len方法获取长度,cap获取容量
如果是简洁声明,不声明数组长度就是切片,譬如

s:=[] int{}//切片
a:=[10] int{1,2,3,4,5,6,7,8,9,10}//数组
c:=a[3,5]//切片c获取数组a下标3到5位元素值,包括3不包括5下标 
d:=a[3:]//下标3到a数组的长度
slice:= make(int[], 4, 6) 创建一个长度为4,容量为6的int类型slice

package mainimport "fmt"
func testModifyElem(s []int) {s[0] = 1fmt.Printf("s inter address is %p \n", s)fmt.Println("s=", s)
}func main()  {fmt.Println("------------------------ slice0 -------------------------")sa := make([]int, 10)fmt.Printf("sa address is %p \n", sa)fmt.Println("sa=", sa)testModifyElem(sa)fmt.Printf("post sa address is %p \n", sa)fmt.Println("post sa=", sa)
}


------------------------ slice0 -------------------------
sa address is 0xc0001220f0
sa= [0 0 0 0 0 0 0 0 0 0]
s inter address is 0xc0001220f0
s= [1 0 0 0 0 0 0 0 0 0]
post sa address is 0xc0001220f0
post sa= [1 0 0 0 0 0 0 0 0 0]


函数内部对slice某个元素的修改,会影响函数外面的slice。
函数内部的slice地址和函数外部的slice是一致的。

package mainimport "fmt"func testModifyElem2(s []int) {s[0] = 1fmt.Printf("函数内部 s inter address is %p \n", s)fmt.Println("函数内部 s=", s)s = append(s, 11)fmt.Printf("函数内部 s inter address(after append) is %p \n", s)fmt.Println("函数内部 s=(after append)", s)
}func main() {fmt.Println("------------------------ slice0 -------------------------")sa := make([]int, 10)fmt.Printf("调用前 sa address is %p \n", sa)fmt.Println("调用前 sa=", sa)testModifyElem2(sa)fmt.Printf("调用后 post sa address is %p \n", sa)fmt.Println("调用后 post sa=", sa)
}

------------------------ slice0 -------------------------
调用前 sa address is 0xc0000a60f0
调用前 sa= [0 0 0 0 0 0 0 0 0 0]
函数内部 s inter address is 0xc0000a60f0
函数内部 s= [1 0 0 0 0 0 0 0 0 0]
函数内部 s inter address(after append) is 0xc0000d6000
函数内部 s=(after append) [1 0 0 0 0 0 0 0 0 0 11]
调用后 post sa address is 0xc0000a60f0
调用后 post sa= [1 0 0 0 0 0 0 0 0 0]

函数内部对slice某个元素的修改,会影响函数外面的slice。
如果函数内部对slice的append操作,不会影响到函数外部slice。
我们的slice len和cap都是10,函数内部的append会导致扩容,扩容之后,地址发生了变化,但是函数外部的slice地址并没有变化。这说明了golang的slice传递slice不是引用传递,而是值传递。

扩容策略

func main(){fmt.Println("------------------------ slice9 -------------------------")slice9 := []int{10, 20, 30, 40}newslice9 := append(slice9, 50)fmt.Printf("Before slice = %v, Pointer = %p, len = %d, cap = %d\n", slice9, slice9, len(slice9), cap(slice9))fmt.Printf("Before newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newslice9, newslice9, len(newslice9), cap(newslice9))newslice9[1] += 10fmt.Printf("After slice = %v, Pointer = %p, len = %d, cap = %d\n", slice9, slice9, len(slice9), cap(slice9))fmt.Printf("After newSlice = %v, Pointer = %p, len = %d, cap = %d\n", newslice9, newslice9, len(newslice9), cap(newslice9))}

输出 结果是:


------------------------ slice9 -------------------------
Before slice = [10 20 30 40], Pointer = 0xc000016100, len = 4, cap = 4
Before newSlice = [10 20 30 40 50], Pointer = 0xc00001c0c0, len = 5, cap = 8
After slice = [10 20 30 40], Pointer = 0xc000016100, len = 4, cap = 4
After newSlice = [10 30 30 40 50], Pointer = 0xc00001c0c0, len = 5, cap = 8

Go 中切片扩容的策略是这样的:

首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)
否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap)
否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)
注意:扩容扩大的容量都是针对原来的容量而言的,而不是针对原来数组的长度而言的。


http://www.ppmy.cn/news/346453.html

相关文章

android 8 奕骆,为耐而生的手机 Innos奕骆D6000评测

说道手机续航能力真是让人头疼的问题,当然也是老生常谈的问题,随着快速充电技术广泛应用到手机上,续航问题才在一定程度上得了缓解,但一天多充仍然不可避免,虽然市面上也出现了许多超续航手机,大电池容量+快速充电续航能力显著,但说道超续航手机比较优秀手机的当属Innos…

HP D6000 盘柜配置

基础设施 HP DL380 Gen8 服务器 System:Centos_6.3 HP Smart Array P431/2G Controller HP D6000 盘柜 P431卡插入服务器PCI-E插槽,通过 SAS线 把盘柜与服务器连接 配置RAID6 重启服务器,按F5进入P431卡配置界面 开始配置,配置RAID6 缓存配置…

android 8 奕骆,奕骆 D6000手机如何重装系统、手机系统怎样重装?

好多朋友对于手机系统的重装还很陌生,遇到手机系统方面的问题会不知所措,甚至花大代价去找维修,其实想要解决手机系统的问题、给手机重装系统是非常的简单事情。下面就一起来了解下: 重装系统的两种方式 一种叫做卡刷:…

JavaScript全解析——npm

npm 的介绍 ●认识 npm ○一个 基于 node 环境的 包管理器 ● npm 的安装 ○不需要安装, 只要安装了 node, 自动安装 npm ●npm 的检测 ○打开命令行, 目录无所谓 ○输入指令: npm --version || npm -v ●npm 的作用 ○下载一切和 js 相关的 第三方 ○相当于是一个 "软…

KW 新闻 | KaiwuDB 亮相数字中国并发布离散制造场景解决方案

4月26-30日,以“加快数字中国建设,推进中国式现代化”为主题的第六届数字中国建设峰会在福州市圆满召开。KaiwuDB 受邀亮相大会参展并发布“离散制造场景解决方案”,旨在以数字化方案驱动生产方式、治理方式变革,推进离散制造业物…

MySQL的索引为什么要下推?

文章目录 一、回表操作 二、主键索引 三、非主键索引 四、低版本操作 五、高版本操作 六、总结 一、回表操作 对于数据库来说,只要涉及到索引,必然绕不过去回表操作。当然这也是我们今天所讲的内容的前提基础。说到回表,我们需要从索引…

window环境下有事无法下载sentry-cli.exe包解决方案

报错:Error: Unable to download sentry-cli binary from解决方案:查看下载配置 可通过修改SENTRYCLI_CDNURL来改变下载包的地址,手动把包下载下来,然后更改地址 window可以使用:set SENTRYCLI_CDNURLxxx&& n…

EDP/DP转HDMI OUT 支持常用分辨率,最大支持4K@60Hz

1. Description(概述) S.EDP-HDMI-4K2K.V1.2是一款信号转接板板,主要是用于将EDP/DP信号转换成HDMI信号,最大分辨率支持到4K60HZ。产品可应用于机顶盒、广告机、会议系统等领域,EDP输入需要符合EDP1.1,EDP1.2标准; 成功案例&#…