你知道的Go切片扩容机制可能是错的

Posted 太白技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你知道的Go切片扩容机制可能是错的相关的知识,希望对你有一定的参考价值。

你好,我是太白,今天和你探索下Go语言的切片扩容机制。

如果觉得文章对你有帮助,记得点赞+关注。目前本公众号没有评论功能,有问题请联系我。

  • 1 前言

  • 2 代码片段1

  • 3 代码片段2

  • 4 growslice源代码

  • 5 代码片段3

  • 6 go1.18beta1的变化

  • 7 总结

  • 上一篇《Go切片与技巧(附图解)》,我们讲到了Go内置函数append操作,当append操作的时候,切片容量如果不够,会触发扩容。

    关于Go切片的扩容机制,网上文章很多,很多结论是这样的:

    结论1:

  • 1、当需要的容量超过原切片容量的两倍时,会使用需要的容量作为新容量。
  • 2、当原切片长度小于1024时,新切片的容量会直接翻倍。而当原切片的容量大于等于1024时,会反复地增加25%,直到新容量超过所需要的容量。
  • 结论2:

  • 在结论1的基础上(切片的预估容量阶段),提到了内存对齐,容量计算完了后还要考虑到内存的高效利用,进行内存对齐。
  • 其中结论1,可能最让人熟知。

    本文将和你一起来探索下这个切片的扩容机制,看看到底是不是这样的。

    我们来看下下面的这端代码,执行结果是6,为什么不是8呢?这个和前言提到的结论1貌似有冲突。

    为了解释上面的代码片段2,我们开看下go的runtime帮我们干了什么。

    我们可以通过delve来调式我们的Go代码。这边演示的Go版本:1.16.5

    通过打断点b main.main、然后用si指令定位到以下代码,runtime.growslice()正式Go扩容的源代码。

    带入变量变成capmem = roundupsize(5 * 8),所以主要是roundupsize影响了最终的结果。

    通过debug,我们发现执行到了return uintptr(class_to_size[size_to_class8[divRoundUp(size, smallSizeDiv)]])

    特别提下,下面两端切片类型不同,扩容的结果也不同,大家可以自行debug下,所以前言提到的结论1中翻倍的结论也是有问题的。

    上面分析是基于go1.16.5的,太白注意到go1.18之后,growslice改了

    1024变成了256,公式也改了,newcap += newcap / 4变成了newcap += (newcap + 3*threshold) / 4,这边我就不展开了。给大家贴下代码:

  • 1、前言中的结论1讲法不严谨,讲对了一部分(代码片段1可知),不同的切片类型,扩容值可能是不同的(代码片段3可知),Go的runtime分配内存的时候,会调用roundupsize,取整内存值(代码片段2可知)。
  • 2、前言中的结论2比结论1好一点,但它是基于结论1的,随着Go版本的迭代,这个结论也会过时。
  • 3、Go切片的扩容机制还是比较复杂的,受到Go版本、操作系统、数据类型等因数,其机制都会有不同,要具体情况具体分析,不要单一的记下一个结论就觉得ok。
  • 4、网上的文章参差不齐,大家在搜资料的时候,需要我们去甄别,最好自己去验证下。
  • 读完文章如果对你有帮助,记得关注下方

    关于学外语,这些人人都知道的“常识”,可能是错的……

    对于大多数人来说,无论上什么学校,修什么专业,外语都是一门绕不开的必修课。这门课看似不难,却让很多人头疼不已。

    说它“不难”,是因为关于外语学习的资源非常丰富,图书、课程、App、大V经验分享,应有尽有。然而,那些五花八门的资料和多种多样的学习技巧,并不是每一份、每一条都切实可用。比如下面马上就要提到的这些,它们可能是很多人从小听到大的“常识”,却不一定能给出可靠的学习建议。

    01

    年龄大了就学不好外语了?

    我们常说,儿童是语言的天才。而随着年龄的增长,这种原本人人都有的天赋好像会逐渐退化,直到消失。但这到底是不是真的呢?其实对于这个问题,学界是存在一些分歧的。

    美国纽约市立大学曾经展开过一项跟踪调查,观察汉语母语者来到美国之后学习英语的情况。如果我们只看结果,会发现年龄小的受访者接受英语的速度确实更快。但有学者提出,这种结果背后可能另有原因,年龄较大的受访者即便身在美国也能找到华语资讯和电影,并且在小圈子里交到说汉语的朋友。而年龄很小的受访者大多不具备这样的能力,他们没有别的选择,只能尽快接受英语坏境。两个人群的学习动力大不相同。

    回到问题本身,在20世纪70年代后期,有研究者仔细分析了过往的研究成果,发现儿童更容易把外语学到接近母语者的程度,但成年人发达的认知能力能够帮助他们更快地掌握外语知识。这意味着成年人在外语学习方面也有一些儿童所不具备的优势。事实上,成年后才开始学习外语,水平却非常可观的学习者并不罕见。如果真的想要掌握外语,成年学习者应该做的第一件事,恐怕是停止对年龄的抱怨。

    02

    母语一定会干扰外语学习?

    在外语课堂上,我们经常听到老师强调一件事,那就是不要以母语的习惯来揣测外语,而要努力养成所学语种的思维方式。这当然是有道理的,但这样的话听多了,我们很容易产生一种误解,以为母语在外语学习中的作用一定是负面的。

    母语对外语学习产生的影响叫作“语言迁移”。语言迁移的作用是多样的,它有时是干扰因素,有时却能辅助外语学习。语言总会有一些共同的规律,这是语言学习的基础,也为语言迁移的正面效果留下了空间。但语种之间也总是存在差异,如果学习者没能消化这些差异,语言迁移便会产生负面效果。

    从另一个角度看,人们在学习新知识的时候,总是需要从已有的知识出发,所以迁移是一种普遍存在的现象。它在很多时候就是学习的第一步。真正值得担心的并不是迁移本身,而是满足于用母语的规律去认识外语,不愿更加深入地了解另一种语言。

    03

    向“外语达人”取经就能学好外语?

    我们总是好奇那些擅长外语的人是怎么学习的,他们的成功背后是否藏着窍门。然而,在急着取经的时候,我们可能忽略了一个问题——学习方法本身就是因人而异的。

    在20世纪80年代,学者韦舍(Wesche)做过这样一项实验。先通过测试将学习者分为语言分析能力强的小组和记忆能力强的小组,接着将每组学生再分为两组,分别采用“以语法为中心的教学法”和“以背诵记忆为中心的教学法”来授课。结果发现教学方法和个人情况相匹配时,学习者更积极,成绩也更好。

    那么,如果一位擅长分析的学习者执意要和一位记忆力强的学霸取经,会发生什么事呢?他获得的学习方法很可能无法匹配自身情况,学习效果没有起色,学习者的自信心也会大受打击。

    “因材施教”也是一个老话题了,但我们在自主学习的时候,反倒最容易急着照搬“成功经验”。事实上,了解自身情况、适时调整方法也是学习中必不可少的环节,能够把这一步做好的人不仅能学好知识,更能拥有自己的方法论。

    04

    外语考试的应试技巧有百利而无一害?

    考试对于学习者的重要性不可否认。为了考出好成绩,学习一些技巧也是必要的。但这些小技巧并非毫无害处,有时正是它们造成了外语学习的瓶颈。

    比如,有一种非常典型的技巧,叫寻找关键词。通过寻找关键词来解题,我们可以在考场上应对一些并没有完全看懂的文段。你当然可以说这很聪明,但如果一个人总能借此考出满意的成绩,他很可能会满足于此,而不会在考试之后认真复盘,把一知半解的文段看明白。长此以往,他的外语水平也会停滞不前。

    很多已经学了几年外语的人都会遇到类似的情况。他们似乎小有成绩,却总是难以更进一步。原因就在于,对他们来说,已有的外语知识加上一些小聪明已足够应对多数事务。继续深入学习外语的动力也就没有那么强了。所以,如果想要熟练掌握一门外语,而不是一直停留在中等水平,我们需要对那些好用的小技巧心怀警惕。

    05

    学外语的素材越“讲究”越好?

    除了“怎样学”,“用什么学”也是一个重要问题。无论是书籍还是课程,现在的外语学习资源总喜欢强调“优质”,动辄取材自名家名作,甚至有机构扬言能用一本原版经典小说让学习者彻底蜕变。

    名家名作当然是非常“讲究”的素材,但“讲究”的素材一定是好素材吗?认知科学教授白井恭弘提醒我们,语言习得的关键是理解输入内容。如果素材太难,或者涉及太多晦涩的背景知识,那么学习过程就很难完成有效输入。文学经典内容深邃,即便是阅读母语版本也要反复品味才能体会作者的深意,有些名篇关乎特殊年代,对人文历史没有兴趣的人也很难看出其中的妙处。

    所以,与其盲目追求“讲究”,不如在自己感兴趣的领域内寻找难度合适的素材。集中学习和自己专业/职业相关的外语素材就是一个不错的选择。不断积累专业领域的单词,外语理解能力就会随之提高,单一领域内的外语水平提高以后,再学习其他领域的语言知识也会更加顺利。

    写在最后

    关于学外语,还有很多问题值得探讨。比如,学外语必须依照特定的顺序吗?我们能“无意识”地学会外语吗?双母语的人和其他人有什么不同?等等。

    当语言成为一门科学,人们已不再满足于以个人经验来解答这些问题。第二语言习得应运而生。这是一门综合了语言学、心理学、教育学,专门研究人们如何学习第二门语言的学科。以此为业的学者研究各式各样的学习方法和过程,以科学的方式解释外语学习。

    我们能否从他们那里获得一些可靠的指导?当然可以。普通人往往没有时间和精力去钻研论文,不过没关系,有一本书清楚简练地介绍了第二语言习得的研究成果,可以帮你厘清外语学习里的各种说法从何而来,让你从系统的高度来调整自己的学习方法——

    《如何科学学外语》

    [日]白井恭弘 著

    甘菁菁 译

    本书是基于“第二语言习得”理论的外语学习科普读物。书中围绕“如何科学学外语”这一问题,从实证的角度解读了人类掌握母语以及外语的原理,并以此归纳出科学的外语学习方法。此外,本书针对“学外语是否越早越好”“口语重要还是语法重要”“输入和输出如何平衡”等实际问题,从外语学习者、外语教授者(教师、家长)两种立场出发,科学分析了“儿童外语学习”“学校外语教育”中的常见误区,并结合实际的研究项目,介绍了科学、高效的外语学习原则与方法。本书适合作为广大外语学习者的学习方法指南,也适合外语教师、外语研究者、家长阅读参考等。

    本书特色

    • 剖析语言本质,澄清外语学习误区,寻求高效外语学习法

    • 加州大学洛杉矶分校应用语言学博士、剑桥大学《第二语言习得研究》编委——白井恭弘 第二语言习得理论,科普力作

    • 用科学方法为外语学习注入生机,让热情与努力不再成为徒劳

    • 日本《英语教育》杂志、日本法语学会会刊推荐图书

    作者简介

    白井恭弘 Yasuhiro Shirai,美国加州大学洛杉矶分校应用语言学博士。美国凯斯西储大学认知科学教授。日本语言科学会第三届理事长。生于日本东京,毕业于日本上智大学外语系英语专业,获得于美国加州大学洛杉矶分校硕士学位(英语教学方向)和博士学位(应用语言学方向)。历任日本大东文化大学外语系英语专业助理教授、美国康奈尔大学现代语专业助理教授、美国康奈尔大学亚洲研究专业副教授、美国匹兹堡大学语言专业教授。现任美国凯斯西储大学认知科学教授,研究方向为语言学、语言习得论。 著有《词汇与语法习得》《东亚心理语言学手册:日语》《外语学习的成功者和失败者》《英语教师的二语习得论入门》《语言的力量——欢迎走进应用语言学的世界》等。

    目录详情

    左右滑动查看更多>>>

    文末互动

    说一说你曾经尝试过的外语学习方法。你觉得效果怎么样?我们会在精选留言中选出 3 位获得赠书。活动截至:2021.8.20。

    喜欢这篇文章?点个“在看”吧~▼

    以上是关于你知道的Go切片扩容机制可能是错的的主要内容,如果未能解决你的问题,请参考以下文章

    关于学外语,这些人人都知道的“常识”,可能是错的……

    GoLang中的切片扩容机制

    注意,你所做的 A/B 实验,可能是错的!

    不知是对是错的道路

    这样在 C# 使用 LongRunnigTask 是错的

    数组/切片以及扩容的概念 | Go语言基础