游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Golang切片原理

  在Golang语言开发过程中,我们经常会用到数组和切片数据结构,数组是固定长度的,而切片是可以扩张的数组,那么切片底层到底有什么不同?接下来我们来详细分析一下内部实现。一、内部数据结构
  首先我们来看一下数据结构typeslicestruct{arrayunsafe。Pointer数据lenint长度capint容量}
  这里的array其实是指向切片管理的内存块首地址,而len就是切片的实际使用大小,cap就是切片的容量。
  我们可以通过下面的代码输出slice:packagemainimport(fmtunsafe)funcmain(){data:make(〔〕int,0,3)fmt。Println(unsafe。Sizeof(data),len(data),cap(data))Output:24,0,3通过指针方式拿到切片内部的值ptr:unsafe。Pointer(data)opt:(〔3〕int)(ptr)fmt。Println(opt〔0〕,opt〔1〕,opt〔2〕)Output:824634891936,0,3dataappend(data,4)fmt。Println(unsafe。Sizeof(data))Output:24shallowCopy:data〔:1〕ptr1:unsafe。Pointer(shallowCopy)opt1:(〔3〕int)(ptr1)fmt。Println(opt1〔0〕)Output:824634891936}
  这么分析下来,我们可以了解如下内容:切片的数据结构大小是24,int占8字节,指针占8字节在不发生扩容的情况下,切片指向的首选地址不变常用的关于切片的方法有make,copy二、声明
  使用一个切片通常有两种方法:
  一种是varslice〔〕int,称为声明;
  另一种是slicemake(〔〕int,len,cap)这种方法,称为分配内存。三、创建make
  创建一个slice,实质上是在分配内存。funcmakeslice(ettype,len,capint)unsafe。Pointer{获取需要申请的内存大小mem,overflow:math。MulUintptr(et。size,uintptr(cap))ifoverflowmemmaxAlloclen0lencap{mem,overflow:math。MulUintptr(et。size,uintptr(len))ifoverflowmemmaxAlloclen0{panicmakeslicelen()超过内存限制超过最大分配量长度小于0}panicmakeslicecap()长度大于容量}分配内存runtimemalloc。goreturnmallocgc(mem,et,true)}
  这里跟一下细节,math。MulUintptr是基于底层的指针计算乘法的,这样计算不会导致超出int大小,这个方法在后面会经常用到。funcMulUintptr(a,buintptr)(uintptr,bool){ifab1(4sys。PtrSize)a0{sys。PtrSize8returnab,falsea和b都小于32位,乘积肯定小于64位}overflow:bMaxUintptraMaxUintptruintptr(0),也就是64个1returnab,overflow}
  同样,对于int64的长度,也有对应的方法funcmakeslice64(ettype,len64,cap64int64)unsafe。Pointer{len:int(len64)ifint64(len)!len64{panicmakeslicelen()}cap:int(cap64)ifint64(cap)!cap64{panicmakeslicecap()}returnmakeslice(et,len,cap)}
  而实际分配内存的操作调用mallocgc这个分配内存的函数,这个函数以后再分析。四、扩容机制
  我们了解切片和数组最大的不同就是切片能够自动扩容,接下来看看切片是如何扩容的funcgrowslice(ettype,oldslice,capint)slice{前置条件ifcapold。cap{panic(errorString(growslice:capoutofrange))}如果新切片的长度为0,返回空数据,长度为旧切片的长度ifet。size0{returnslice{unsafe。Pointer(zerobase),old。len,cap}}1、先记录原先的容量newcap:old。cap2、尝试2倍扩容doublecap:newcapnewcapifcapdoublecap{如果指定容量大于原有容量的2倍,则按新增容量申请newcapcap}else{3、如果指定容量小于原容量2倍,则按以下的计算方式为新容量ifold。len1024{如果原容量小于1024,新容量是原容量的2倍newcapdoublecap}else{原容量大于1024,按原容量的1。25倍递增for0newcapnewcapcap{newcapnewcap4}ifnewcap0{校验容量是否溢出newcapcap}}}varoverflowboolvarlenmem,newlenmem,capmemuintptr为加速计算(不用乘除法)对于2的幂,使用变位处理下面的处理使内存对齐switch{caseet。size1:lenmemuintptr(old。len)newlenmemuintptr(cap)capmemroundupsize(uintptr(newcap))overflowuintptr(newcap)maxAllocnewcapint(capmem)caseet。sizesys。PtrSize:lenmemuintptr(old。len)sys。PtrSizenewlenmemuintptr(cap)sys。PtrSizecapmemroundupsize(uintptr(newcap)sys。PtrSize)overflowuintptr(newcap)maxAllocsys。PtrSizenewcapint(capmemsys。PtrSize)caseisPowerOfTwo(et。size):2的幂varshiftuintptrifsys。PtrSize8{Maskshiftforbettercodegeneration。shiftuintptr(sys。Ctz64(uint64(et。size)))63}else{shiftuintptr(sys。Ctz32(uint32(et。size)))31}lenmemuintptr(old。len)shiftnewlenmemuintptr(cap)shiftcapmemroundupsize(uintptr(newcap)shift)overflowuintptr(newcap)(maxAllocshift)newcapint(capmemshift)default:lenmemuintptr(old。len)et。sizenewlenmemuintptr(cap)et。sizecapmem,overflowmath。MulUintptr(et。size,uintptr(newcap))capmemroundupsize(capmem)newcapint(capmemet。size)}判断是否会溢出,是否会超出可分配ifoverflowcapmemmaxAlloc{panic(errorString(growslice:capoutofrange))}内存分配varpunsafe。Pointerifet。ptrdata0{pmallocgc(capmem,nil,false)回收内存memclrNoHeapPointers(add(p,newlenmem),capmemnewlenmem)}else{Note:cantuserawmem(whichavoidszeroingofmemory),becausethenGCcanscanuninitializedmemory。pmallocgc(capmem,et,true)iflenmem0writeBarrier。enabled{gcOnlyshadethepointersinold。arraysinceweknowthedestinationsliceponlycontainsnilpointersbecauseithasbeenclearedduringalloc。bulkBarrierPreWriteSrcOnly(uintptr(p),uintptr(old。array),lenmem)}}数据拷贝memmove(p,old。array,lenmem)returnslice{p,old。len,newcap}}
  这里可以看到,growslice是返回了一个新的slice,也就是说如果发生了扩容,会发生拷贝。
  所以我们在使用过程中,如果预先知道容量,可以预先分配好容量再使用,能提高运行效率。五、深拷贝
  copy这个函数在内部实现为slicecopyfuncslicecopy(to,fmslice,widthuintptr)int{前置条件iffm。len0to。len0{return0}n:fm。lenifto。lenn{nto。len}元素长度为0,直接返回ifwidth0{returnn}size:uintptr(n)width拷贝内存ifsize1{(byte)(to。array)(byte)(fm。array)knowntobeabytepointer}else{memmove(to。array,fm。array,size)}returnn}
  还有关于字符串的拷贝funcslicestringcopy(to〔〕byte,fmstring)int{前置条件iflen(fm)0len(to)0{return0}n:len(fm)iflen(to)n{nlen(to)}memmove(unsafe。Pointer(to〔0〕),stringStructOf(fm)。str,uintptr(n))returnn}
  这里显示了可以把string拷贝成〔〕byte,不能把〔〕byte拷贝成string。六、总结
  1、切片的数据结构是array内存地址,len长度,cap容量
  2、make的时候需要注意容量长度分配的内存大小要小于264,并且要小于可分配的内存量,同时长度不能大于容量。
  3、内存增长的过程:如果指定的容量大于原先的2倍,就按照指定的容量如果原先的容量小于1024,按2倍容量扩张如果原先的容量大于1024,就按1。25倍扩张,会小于指定的容量容量大小确定完之后,会进行内存对齐
  4、当发生内存扩容时,会发生拷贝数据的现象,影响程序运行的效率,如果可以,要先分配好指定的容量
  5、关于拷贝,可以把string拷贝成〔〕byte,不能把〔〕byte拷贝成string。

Atthezoo第1课时教学设计教学内容:Let’stalkLet’spractice教学目标:1、能听、说、认读形容词big、small、long、short。能用lookatIthasI……人造卫星ampnbsp宇宙速度教学目标知识目标:1、通过对行星绕恒星的运动及卫星绕行星的运动的研究,使学生初步掌握研究此类问题的基本方法:万有引力作为圆周运动的向心力;2、使学生对人造卫星……三朝元老的成语接龙三朝元老:原指受三世皇帝重用的臣子。现在用来指在一个机构里长期工作过的资格老的人。品学网小编为大家整理了三朝元老的成语接龙,希望大家喜欢。三朝元老成语接龙:三朝元老……大班健康教案手指操一节:大树(伸出中指、无名指、小指三个指)下面有个洞(另二指成圆),住着可爱小虫虫(作轮指动作、先是大拇指往回收、另四指分别回收后作个波浪),大虫出洞探探头(大拇指伸进洞后向上……文具盒阅读文章及参考答案文具盒娘说,女孩子家能识几个字就行了,遭那个罪咋?英子听了,眼泪就扑塌扑塌掉下来。常沾泪的那地方便有了印痕,似两片干柳叶。过年了,乡里分给村里一些市里人捐的衣、物,……秘书工作有关手的180个成语比手划脚比:比拟。形容说话时用手势示意或加强语气搏手无策搏手:两手相扭。指扭着双手,毫无办法触手可及近在手边,一伸手就可以接触到垂手而得形容得来毫不费力气……阅读练习及答案参考伤仲永金溪民方仲永,世隶耕。仲永生五年,未尝识书具,忽啼求之。父异焉,借旁近与之,即书诗四句,并自为其名。其诗以养父母、收族为意,传一乡秀才观之。自是指物作诗立就,其文理……丰富词语的造句集锦1。他的丰富的经验使他谨慎从事。2。周末我的假期很丰富,一会儿要写作业,一会儿跟妈妈学家务,一会还要像个小兔子一样蹦蹦跳跳的和小伙伴去玩耍。3。超市里货架上的货物太……三年级美术美丽的草原教案教学反思美丽的草原教案设计、反思教材分析美丽的草原一课是造型表现和设计应用相结合的艺术综合实践课。一谈到草原立刻就会让人联想的那是蒙族儿女生活的地方,联想到蒙族歌手腾格尔的……灰椋鸟第一课时教学设计教学目标:1、能正确、流利地朗读课文,随课文理解词语意思。2、品读第二自然段,感受课文描绘的美好意境,受到美的熏陶并能听写。3、通过朗读训练和赛诗比赛,激发学……小学音乐采山教案【教学目标】1、指导学生用欢快、活泼的情绪,有感情地演唱歌曲《采山》,并乐于用多种艺术形式来表现歌曲,让学生明白劳动最光荣的道理。2、能表达歌曲节奏,并能在实践活动……对花教学反思身为一名人民老师,课堂教学是我们的任务之一,通过教学反思可以很好地改正讲课缺点,优秀的教学反思都具备一些什么特点呢?以下是小编为大家收集的对花教学反思,仅供参考,希望能够帮助到……
中秋档首日票房3。6亿元破纪录诛仙为单日冠军IT之家9月14日消息昨日,电影中秋档拉开帷幕,《诛仙》、《名侦探柯南:绀青之拳》等多款电影纷纷上映。据新京报报道,猫眼专业版数据显示,中秋档首日票房达3。675亿元,超……2019年中国国内电影票房突破200亿元,5部影片突破10亿IT之家4月14日消息根据猫眼电影的数据,截至本月13日,2019年中国内地电影票房突破200亿元,共用时103天,相比于2018年第一季度电影票房突破200亿元的速度慢了将近……2018好莱坞最赚钱十大电影公布复仇者联盟3净赚5亿美元排第IT之家4月9日消息2018年好莱坞影片中最赚钱的有哪些呢?外媒deadline梳理总结了好莱坞年度赚得最多的电影前十位,其中《复仇者联盟3》以5亿美元利润登顶,《黑豹》《海王……冰灯教学设计第一课时教学目标:1、正确、流利、有感情地朗读诵课文。2、认识生字12个。3、理解课文内容,了解父亲对儿子的关爱。教学重难点:1、正确、流利……天猫公布双十一10亿宝贝中奖用户!这次是个男的IT之家11月12日消息今天凌晨零点,2018年天猫双11全球狂欢节正式落下帷幕,交易额最终定格在2135亿元。根据2018天猫双十一实时交易数据现实,4分20秒,成交额超19……给高尔基的信阅读答案最近接到你的那封信,给我不少快乐。我诚心地感谢你。我那篇《叔叔万亚》是很久很久以前写的,我从没有看见在舞台上演过。近年各地的小戏院常常公演这本戏。我对于自己写的戏剧向不怎么高兴……欣赏军旗上飘扬着我们的歌你是这样的人当兵的人在哪里作者单位:河北省曲阳县燕赵镇南留营中学一、教学目标1知识与技能:通过欣赏军旗上《飘扬着我们的歌》、《你是这样的人》、《当兵的人在哪里》,感受、体验其音乐内容、音乐情……清华大学总裁班微信群里众筹开公司,负债300万申请破产IT之家10月28日消息IT之家从海淀法院官网获悉,近日,海淀法院受理了一起债务人自行申请破产清算的案件。债务人成立于2014年12月,系经微信群成员众筹设立的一家非上市股份有……泰晤士报世界大学排名榜2019出炉清华大学居22位,亚洲第一IT之家9月27日消息近日《泰晤士高等教育》(THE)发布了2019世界大学排名,清华大学居22位,击败新加坡国立大学排亚洲第一,北大则为31位,香港大学、香港科技大学分别居3……海量主播被直播平台巨额索赔,这是为何?2018年11月20日,广东省广州市中级人民法院公布了对《王者荣耀》主播嗨氏(江海涛)与广州虎牙信息科技有限公司之间纠纷的二审判决。在判决书中,法院判定江海涛需要向虎牙提供49……2018网络直播冰火两重天对于今年的直播行业来说,年初的热闹和年末的寂寥,简直是冰火两重天。今年1月,直播答题突然火爆,映客、陌陌、一直播等平台纷纷入局,一度让人以为直播将迎来第二春,但随着监管介……车辙的解释及造句车辙拼音【注音】:chezhe车辙解释【意思】:车辆经过时车轮压在道路上凹下去的痕迹。车辙造句:1、这条路留有很深的车辙。2、如果行进到半山……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网