浅论go语言的美好和丑陋 go语言很火吗

【golang详解】go语言GMP(GPM)原理和调度

Goroutine调度是一个很复杂的机制,下面尝试用简单的语言描述一下Goroutine调度机制,想要对其有更深入的了解可以去研读一下源码。

为新乡县等地区用户提供了全套网页设计制作服务,及新乡县网站建设行业解决方案。主营业务为成都网站制作、网站建设、新乡县网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

首先介绍一下GMP什么意思:

G ----------- goroutine: 即Go协程,每个go关键字都会创建一个协程。

M ---------- thread内核级线程,所有的G都要放在M上才能运行。

P ----------- processor处理器,调度G到M上,其维护了一个队列,存储了所有需要它来调度的G。

Goroutine 调度器P和 OS 调度器是通过 M 结合起来的,每个 M 都代表了 1 个内核线程,OS 调度器负责把内核线程分配到 CPU 的核上执行

模型图:

避免频繁的创建、销毁线程,而是对线程的复用。

1)work stealing机制

当本线程无可运行的G时,尝试从其他线程绑定的P偷取G,而不是销毁线程。

2)hand off机制

当本线程M0因为G0进行系统调用阻塞时,线程释放绑定的P,把P转移给其他空闲的线程执行。进而某个空闲的M1获取P,继续执行P队列中剩下的G。而M0由于陷入系统调用而进被阻塞,M1接替M0的工作,只要P不空闲,就可以保证充分利用CPU。M1的来源有可能是M的缓存池,也可能是新建的。当G0系统调用结束后,根据M0是否能获取到P,将会将G0做不同的处理:

如果有空闲的P,则获取一个P,继续执行G0。

如果没有空闲的P,则将G0放入全局队列,等待被其他的P调度。然后M0将进入缓存池睡眠。

如下图

GOMAXPROCS设置P的数量,最多有GOMAXPROCS个线程分布在多个CPU上同时运行

在Go中一个goroutine最多占用CPU 10ms,防止其他goroutine被饿死。

具体可以去看另一篇文章

【Golang详解】go语言调度机制 抢占式调度

当创建一个新的G之后优先加入本地队列,如果本地队列满了,会将本地队列的G移动到全局队列里面,当M执行work stealing从其他P偷不到G时,它可以从全局G队列获取G。

协程经历过程

我们创建一个协程 go func()经历过程如下图:

说明:

这里有两个存储G的队列,一个是局部调度器P的本地队列、一个是全局G队列。新创建的G会先保存在P的本地队列中,如果P的本地队列已经满了就会保存在全局的队列中;处理器本地队列是一个使用数组构成的环形链表,它最多可以存储 256 个待执行任务。

G只能运行在M中,一个M必须持有一个P,M与P是1:1的关系。M会从P的本地队列弹出一个可执行状态的G来执行,如果P的本地队列为空,就会想其他的MP组合偷取一个可执行的G来执行;

一个M调度G执行的过程是一个循环机制;会一直从本地队列或全局队列中获取G

上面说到P的个数默认等于CPU核数,每个M必须持有一个P才可以执行G,一般情况下M的个数会略大于P的个数,这多出来的M将会在G产生系统调用时发挥作用。类似线程池,Go也提供一个M的池子,需要时从池子中获取,用完放回池子,不够用时就再创建一个。

work-stealing调度算法:当M执行完了当前P的本地队列队列里的所有G后,P也不会就这么在那躺尸啥都不干,它会先尝试从全局队列队列寻找G来执行,如果全局队列为空,它会随机挑选另外一个P,从它的队列里中拿走一半的G到自己的队列中执行。

如果一切正常,调度器会以上述的那种方式顺畅地运行,但这个世界没这么美好,总有意外发生,以下分析goroutine在两种例外情况下的行为。

Go runtime会在下面的goroutine被阻塞的情况下运行另外一个goroutine:

用户态阻塞/唤醒

当goroutine因为channel操作或者network I/O而阻塞时(实际上golang已经用netpoller实现了goroutine网络I/O阻塞不会导致M被阻塞,仅阻塞G,这里仅仅是举个栗子),对应的G会被放置到某个wait队列(如channel的waitq),该G的状态由_Gruning变为_Gwaitting,而M会跳过该G尝试获取并执行下一个G,如果此时没有可运行的G供M运行,那么M将解绑P,并进入sleep状态;当阻塞的G被另一端的G2唤醒时(比如channel的可读/写通知),G被标记为,尝试加入G2所在P的runnext(runnext是线程下一个需要执行的 Goroutine。), 然后再是P的本地队列和全局队列。

系统调用阻塞

当M执行某一个G时候如果发生了阻塞操作,M会阻塞,如果当前有一些G在执行,调度器会把这个线程M从P中摘除,然后再创建一个新的操作系统的线程(如果有空闲的线程可用就复用空闲线程)来服务于这个P。当M系统调用结束时候,这个G会尝试获取一个空闲的P执行,并放入到这个P的本地队列。如果获取不到P,那么这个线程M变成休眠状态, 加入到空闲线程中,然后这个G会被放入全局队列中。

队列轮转

可见每个P维护着一个包含G的队列,不考虑G进入系统调用或IO操作的情况下,P周期性的将G调度到M中执行,执行一小段时间,将上下文保存下来,然后将G放到队列尾部,然后从队列中重新取出一个G进行调度。

除了每个P维护的G队列以外,还有一个全局的队列,每个P会周期性地查看全局队列中是否有G待运行并将其调度到M中执行,全局队列中G的来源,主要有从系统调用中恢复的G。之所以P会周期性地查看全局队列,也是为了防止全局队列中的G被饿死。

除了每个P维护的G队列以外,还有一个全局的队列,每个P会周期性地查看全局队列中是否有G待运行并将其调度到M中执行,全局队列中G的来源,主要有从系统调用中恢复的G。之所以P会周期性地查看全局队列,也是为了防止全局队列中的G被饿死。

M0

M0是启动程序后的编号为0的主线程,这个M对应的实例会在全局变量rutime.m0中,不需要在heap上分配,M0负责执行初始化操作和启动第一个G,在之后M0就和其他的M一样了

G0

G0是每次启动一个M都会第一个创建的goroutine,G0仅用于负责调度G,G0不指向任何可执行的函数,每个M都会有一个自己的G0,在调度或系统调用时会使用G0的栈空间,全局变量的G0是M0的G0

一个G由于调度被中断,此后如何恢复?

中断的时候将寄存器里的栈信息,保存到自己的G对象里面。当再次轮到自己执行时,将自己保存的栈信息复制到寄存器里面,这样就接着上次之后运行了。

我这里只是根据自己的理解进行了简单的介绍,想要详细了解有关GMP的底层原理可以去看Go调度器 G-P-M 模型的设计者的文档或直接看源码

参考: ()

()

浅谈英语课堂教学中德育渗透

传授知识是德育的基础,而德育则是传授知识的目的和归宿。因此在教学过程中把知识教学纳入德育轨道,才能真正实现其英语教学的德育功能。以下是由我收集整理的浅谈英语课堂教学中德育渗透,欢迎阅读!

浅谈英语课堂教学中德育渗透(一)

一、 教育 学生树立正确的服务意识,养成良好的职业道德

目前我校英语课使用的教材是专为中等职业学校编写的《 实用英语 》,其章节的安排是以话题为主线,体现交际服务功能。课堂上我特别注重结合所学内容教育学生树立正确的服务意识,养成良好的职业道德。如学习Booking a Ticket(订票)一课时,教育学生尊重每位乘客,做到热情耐心,对工作高度负责。学习At the Bank(在银行)时,教育学生从事金融工作要意志坚定,洁身自爱,绝不可铸成一失足成千古恨的憾事。讲解学科知识的同时,有意识地通过学生的情景会话表演,使他们明确作为服务人员应该怎样、不应该怎样,思想道德不断提高。

充分利用课堂教学培养学生爱业、敬业、乐业的精神。如在给酒店管理专业学生上英语专业课的时候,我时常有意设计一些顾客抱怨甚或投诉的会话实例。一方面告诉学生如何用英语进行表述,另一方面引导学生如何正确处理。即注意下列十大步骤:(1)注意倾听;(2)保持冷静;(3)同情客人;(4)维护客人的自尊心;(5)给客人以足够的重视;(6)记录;(7)把将要采取的 措施 告诉投诉者;(8)确定解决问题所需的时间;(9)监督补救措施的执行情况;(10)信息反馈。另外我们知道,在酒店如从事行李员或西餐服务工作,常常会遇到客人给小费等问题,教育学生作为中国人我们应有起码的自尊,同时也尊重别国的礼仪礼节,遇到这种情况可以友好地回答:�t� very kind of you. But we don't accept tips.Thank you all the same.?您真好,可是我们不能收小费,同样要谢谢您。)

良好职业道德的形成是一个漫长的过程,作为教师我们要善于抓住适当的教育契机,使学生从切身的体会和感受中悟到作为一名服务人员必备的道德准则,从而实现职业教育为社会培养合格劳动者的最终目标。

二、采用丰富多彩的教学形式,进行德育渗透

德国教育学家赫尔巴特曾经指出:“教学如果没有进行道德教育,只是一种没有目的的手段;道德教育如果没有教学,就是一种失去了手段的目的。”

因此我们必须明确教学的宏观目标不仅仅在于向学生传授本学科的知识,更重要的是使学生从英语课的学习中得到爱国主义、美育等多方面教育。英语课堂上讲到学好英语的同时不忘强调本民族语言的重要性。学生们现在已经深知没有良好的汉语功底,外国语很难上升到一个更高的层次。开课伊始就教会学生homeland/motherland(祖国),hometown(家乡),Dalian Secondary Vocational and Technical school of Tourism(大连旅游职业中专),Hotel Management(酒店管理)等词汇。让学生在掌握自己国家、学校、专业名称这些英语词句的过程中更加深了对祖国、家乡的热爱,将德育的主课题爱国主义教育很好地渗透到全体学生的心灵深处。

世间万物皆有美的一面,英语这门语言其自身的美往往学生不能够完全体察。我在平日授课中有意穿插播放或教唱一些优美的英文歌曲,如Right Here Waiting(此情可待),Big Big World(大大的世界)等,让学生亲身感受到极富节奏感的英语语言本身创造出的声音的和谐与美,此 方法 也有助于学生审美情趣的提高。

每天讲授一句英语格言,如:“It's the early bird that caches the worm(笨鸟先飞)”,“Constant dropping wears away a stone(滴水穿石)”,“Every step leaves its print(一步一个脚印)”等等。围绕着教育学生如何做人,如何面对困难,战胜困难等方面,选用一些简洁精练、哲理深刻的格言,既丰富了学生的词汇量,又有助于增加语感,培养学生的学习兴趣,从而寓思想教育于英语教学之中。

此外,对学生加强礼仪、礼节方面的训练亦是英语会话课的一个重要内容。“为人师表”四个字并非一句 口号 ,对教师提出了很高的要求。既然为人师表,就要时时处处给学生以榜样。在课上我总是率先带头做到“请”字当先,Please answer this question.(请回答问题);Sit down please.(请坐)。学生在老师的熏陶下逐渐懂得并学会以得体的装束、规范大方的举止站立、行走,到教室前面做英语会话表演。久而久之,学生不良的言行少了,变得站有站相,坐有坐相,职业道德意识不断增强。

总之,在英语教学过程中,对学生进行思想品德教育的方式方法是多样的。只要教师明确德育在育人工作中的作用和地位,就能探索出更多、更有效的方法来。

三、教师应提高自身素质,从而进一步丰富课堂教学内容

特级教师郄禄和曾经说过:“一个教师要解决三种力的问题,即动力、能力、精力。缺乏动力不想干,缺乏能力不会干,缺乏精力不能干。”可见能力在三者之间处于核心地位。伟大的教育家陶行知亦说过:“我认为好的先生不是教书,不是教学生,乃是教学生学。”古人云:“授之以鱼,只供一餐;授之以渔,终身受用。”这些都说明教师在一个人的学习、成长中起着多么重要的作用。可如何教学生学,授之以什么样的“渔”,这都取决于教师自身的素质。

要想在课堂中把德育一点一滴地渗透给学生,就要求教师应不断提高自身素质,加强政治理论学习,提高认识,认真做好本职工作, 爱岗敬业 ,用自己的行动去影响学生。作为英语教师,我们要时刻关注学科前沿,努力掌握新知识、新词汇,研究最新教育理论和教育方法。不仅要吃透教材,还要多方面收集最新 英语学习 资料,多动脑、动口、动手,多方获取酒店、机场等相关实习基地的英语考核信息,丰富教案内容。平时的《英语周报》、《空中美语》等报纸杂志,及每天的《希望英语》教学节目,都可以使我们获得教学所需的资料。由于很多内容比较时尚、新颖,更容易引发学生的学习兴趣。当我们具备了渊博的学识,深邃的思想,高尚的品德,执着的敬业精神,精湛的教学艺术,这一切都会像磁石一样,牢牢地吸引学生,使学生从中得到感染,并把教师当作“智慧和美”的化身,产生钦佩心理,激起学习知识的强烈兴趣。

一分耕耘,一分收获,只要教师多付出努力,多去积累资料,就会使课堂教学更丰富,就会使德育融于英语课教学之中。只要不断地努力探索,外语课的德育渗透一定会结出丰硕的果实。

浅谈英语课堂教学中德育渗透(二)

现在是素质教育时代,它通常以发展学生的各方面素质为核心,德育是素质教育中非常重要的组成部分,并且渗透到学生全面发展的各个方面。在实现教学目标的各科教学中,英语教学中对学生进行德育渗透具有很特别的作用,因为英语它不仅是一门学科,更是一门语言,是信息的载体。在初中英语教学工作中,英语教师的工作一方面表现在对学生传授英语知识,重视学生听说读写各项技能的训练,同时培养学生综合语言运用能力,提高学生 学习英语 的能力;另一方面,在对学生传授知识、培养能力的过程中,还应该加强对学生的思想品德教育,,重视对学生品格的培养,力求帮助学生形成正确的人生观和价值观。做到既教书又育人的作用。教师在注意并利用社会、家庭、学校对学生的正面影响的同时,必须在教学中渗透品德教育,让学生自觉地克服环境因素对英语学习造成的影响,努力学习好英语。教挖掘和利用教材中的德育因素,使学生具有爱国主义、集体主义精神。热爱社会主义国家,弘扬优秀 文化 传统,逐步形成正确的人生观、世界观、价值观,具有高度责任感。英语作为基础学科更加要重视德育教育,要在英语课堂教学中进行德育教育渗透。那么如何在英语教学中渗透德育教育,达到提高教学成绩的目的? 我有以下几点建议:一、通过课堂教学渗透,言传身教,进行养成教育我在初中英语教学中,往往从培养学生的行为规范着手,注重加强学生人文素养,并能把增强学生的爱国意识与社会责任感等德育教育内容自然渗透在教学中,并且取得了较好的效果。初中生可塑性、模仿性很强,教师除了要有较高的知识水平,较强的教育教学能力外,还要具备较强的道德品质。

浅谈英语课堂教学中德育渗透(三)

一谈到德育,很多人都以为那是政治老师的事或是班主任在班会课上的事,与我们的英语课无关,其实这是一种误解,德育教育应该贯穿于每一学科,特别是英语教学更应该注重对学生的德育教育。当然,这种教育不能是简单、空泛的说教,而应该根据具体的教学内容,使之贯穿其内,渗透其中,巧妙结合,有的放矢。笔者在多年的教学实践中逐渐摸索、 总结 出了一些行之有效的方法,对学生的身心发展产生较强的感染作用,提高了他们的综合素质。

一、挖掘德育素材,寓德于教。

英语教材是德育的载体,其中不少对话、日常用语、阅读 文章 都具有丰富的德育修养知识,教师用这样的教材实施教学,在传授英语知识、培养英语运用能力的同时,自然也就渗透了人文性、思想性的教育。因此,教师在组织学生听、说、读、写的过程中,要善于发现教材内容的德育价值,完成对学生思想品德教育的重大任务。另外,教师必须根据教材特点和学生实际,找到并确定教材中训练的内容和思想教育内容的结合点,以防止德育空泛化。如,新目标英语七年级 Unit 3 This is my sister.本单元围绕“家庭成员”这一主题展开听、说、读、写等多种教学活动。教学核心是用英语介绍家人和朋友,在教学过程中,教师可引导学生用英语介绍家人及朋友,通过对人物个性化的描述,介绍家人和了解朋友的家人,增进彼此的了解,建立友谊,从而更好地尊重对方,理解家人。再如,新目标英语七年级 Unit 11 What time do you go to school?该部分学习内容是询问和谈论时间,在课堂教学中学生互相询问或谈论自己或对方的作息时间安排和活动计划,让学生学会合理地安排作息时间,培养学生良好的作息习惯和守时习惯。

二、创设情景,自然启发。

在 英语阅读 教学中,围绕教材的主题,取其精华,精心设问,使学生在理解教材内容的同时,思想上得到熏陶。老师和学生在讨论问题时,自然而然的产生感情上的共鸣,教育者和受教育者都受到了教育。在中学英语教学中,充分挖掘教材内涵的教育意义,根据学生的基础和能力,循序渐进。教师应着力培养学生在日常交际交往中有效地使用语言进行表达,与他人沟通,为今后学习奠定坚实的语言基础。如,新目标英语七年级 Unit 2 Is this your pencil?其教学核心内容是“确认物主”。在教学中可通过寻找主人的游戏和失物招领等活动,通过小组活动,指导学生积极与他人合作,相互学习、相互帮助,共同完成学习任务。并结合教材内容提出问题: Have you ever picked up others’ things or lost anything? What will you do with these things?让学生说出解决的办法,同时通过与学生讨论问题来培养学生拾金不昧、健康向上的良好品德。

在教新目标英语九年级 Unit 1时,针对初三学生面临中考的实际,如何调整学习方式的问题,在教学中围绕“ How do you study for a test?”这一话题组织学生进行交流、讨论及交流各自的 学习方法 并写成书面 报告 ,让学生知己知彼、取长补短、端正 学习态度 ,从而养成刻苦学习的习惯。

在课堂教学中,教师应该充分发扬民主,尊重学生的主体地位和个性差异,用小组讨论模式,启发学生在小组讨论中积极思考,主动交流或 辩论 ,做出判断,寻找自己认为正确的答案,鼓励学生在讨论中考虑他人的观点和意识,协调与他人的分歧;教师还要面向全体学生,保护学生的学习积极性,

创造条件,给后进生以更多的成功机会,使他们看到自己的闪光点,不断增强自信心,增强克服困难的勇气。 三、抓住时机,培养良好习惯。

教学既是认知的过程,同时也是情感培养的过程,新课程标准强调参与、体验和情感的过程,有利于学生在学习中达到知识与技能、过程与方法及情感态度的真正统一。新课标在改变我们的教学方式,同时也要求我们关注学生的情感态度及健康的人格,使素质教育得到真正的体现,因此教师应该结合本校、本班学生的具体实际及时调整课堂教学策略,抓住时机,使学生通过学习既能掌握综合语言技能,又能提升道德情感。

1.尊敬师长、关爱他人教育

现在大多数的孩子自我意识较强,他们往往不懂得关心、爱护别人。教师可在教学活动中有目的地加以引导,以此来激发学生对英语的兴趣,同时也让学生得到良好道德情感的熏陶。如,在 教师节 、 母亲节 、 父亲节 等节日,引导学生制作 贺卡 ,并写上 祝福语 :Happy Teachers’ Day. I am truly grateful to you for what you have done.(我深深地感激您所做的一切。)Thank you for making learning not a dull thing but a great joy.(感谢您使我们把枯燥的学习变成了巨大的乐趣。)/ I love you, Mum. You are the one that we love the most. Have a happy Mother’s Day.(您是我们最爱的人。祝您有一个快乐的母亲节) On this day we honor you, dear mother.(亲爱的妈妈,我们向您致敬。)Thank you for everything over the years, mom.(妈妈,谢谢您这些年来所做的一切。)/ You are the best father in the world. Thanks for holding my hand when I needed it.(谢谢您在我需要的时候伸出援助之手。)在父母生日时送上一句: Happy birthday! 又如在教学单词“ should”时,可设计下列问题:① What should you do when someone is in trouble? ②What should we do in order to make our city more and more beautiful?学生们在讨论这些问题的同时,既得到了 英语口语 的锻炼,学生的道德意识也得到升华。

2.文明礼貌教育

在学习一些礼貌用语时,在让学生了解外国人的礼貌用语的同时也要让学生明白:讲文明、懂礼貌是我们的光荣传统,因而要杜绝打架、骂人等不文明行为。如,在教学 “Sorry./ I’m sorry.”时,可针对学生平时出现的一些不文明行为来创设情景,让学生在情景中去体会“ Sorry./ I’m sorry.”的正确使用,同时也让学生从中明辨是非,学到一些正确处理各种人际关系的方法,逐步养成良好习惯。在教“Thank you./ Thanks a lot.”时告诉学生: It’s very polite to say “Thank you” or “Thanks a lot” when someone help you.(当有人帮助了你,说声谢谢是很有礼貌的。)

3.遵章守纪,讲公共道德的教育。

教师要善于唤起和诱发学生对道德情感的体验,培养学生善良的心灵,使学生真正地感动,以自觉的行动克服一些不良的行为。如教 must/mustn’t时,紧密结合所学语言项目,精心选择贴近学生生活实际的例句,让学生自己做出判断后在下列 句子 加上 must/mustn’t,再表达出来:

Finish our homework on time.

Draw on the wall.

Be quiet at the library.

Wait when the traffic lights are red.

Take good care of follows and trees in school.

Make a lot of noise in class.

Spit on the floor.

完成这一教学活动后,可趁热打铁让学生用 must/mustn’t自由发言,说出在日常生活中应该做好哪些,而哪些是不该做的。此项教学活动既使学生掌握了语言技能,又可对学生进行潜移默化的思想品德教育。

四、树立典范,构建健康和谐的课堂。

学生的道德行为习惯的培养不仅需要认识、情感和意志的支配,而且还需要平时的训练和引导。作为英语教师,在课堂教学中,要面向全体学生,关注学生不同的天赋和智慧,保护学生的学习积极性,不能一味地以成绩的好坏来判断他们,真诚接纳、关爱、宽容每一位学生,真正做到互相尊重,互相关心,以学生的感受为感受,设身处地地为学生着想,并把这种理解传递给学生,让学生能深切地认识到教师的用意,使学生感觉到老师的亲切可信,才能接受老师对他们的一番苦心,这样学生在课堂上信心较足,学习兴趣较浓,并能以愉快的情绪、饱满的精神,产生合作、交流的愿望,积极配合教师的教学活动。学高为师,身正为范,教师的知识水平、工作能力、思想道德、心理素质等都将直接影响到学生培养的质量和效果。在课堂教学中,教师应以其高尚的道德品质、扎实的教学技能、崇高的人格魅力为学生树立典范,以教师自身的高素质去影响学生,让英语课堂弥漫着民主、宽松、和谐、融洽的氛围。

十年树木,百年树人,德育工作要贯穿于学生成长过程的始终,抓住生活中的点滴,把握生活中的一言一行。赫尔巴特曾说过:“教学中如果没有德育渗透,那它只是一种没有目的的手段,德育如果没有教学,就是一种失去手段的目的。”因此,在英语教学中,教师要努力挖掘教材因素,巧妙地设计任务,让学生在掌握知识、发展智力的同时,又引导学生从中自我发掘德育内容,学会自我教育,学会合作,学会做人,以切身的体验去看待问题、关注社会、关注身边的人和事,在身心方面有所进步。总之,教师应该让教学过程成为学生对高尚道德生活与丰富人生的体验,使知识的增长过程同时也成为思想道德素养发展的过程,寓德育教育于无形之中,像春风化雨润物细无声,在潜移默化中对学生起到作用,使学生真正全面发展。

如何看待go语言泛型的最新设计?

Go 由于不支持泛型而臭名昭著,但最近,泛型已接近成为现实。Go 团队实施了一个看起来比较稳定的设计草案,并且正以源到源翻译器原型的形式获得关注。本文讲述的是泛型的最新设计,以及如何自己尝试泛型。

例子

FIFO Stack

假设你要创建一个先进先出堆栈。没有泛型,你可能会这样实现:

type Stack []interface{}func (s Stack) Peek() interface{} {

return s[len(s)-1]

}

func (s *Stack) Pop() {

*s = (*s)[:

len(*s)-1]

}

func (s *Stack) Push(value interface{}) {

*s = 

append(*s, value)

}

但是,这里存在一个问题:每当你 Peek 项时,都必须使用类型断言将其从 interface{} 转换为你需要的类型。如果你的堆栈是 *MyObject 的堆栈,则意味着很多 s.Peek().(*MyObject)这样的代码。这不仅让人眼花缭乱,而且还可能引发错误。比如忘记 * 怎么办?或者如果您输入错误的类型怎么办?s.Push(MyObject{})` 可以顺利编译,而且你可能不会发现到自己的错误,直到它影响到你的整个服务为止。

通常,使用 interface{} 是相对危险的。使用更多受限制的类型总是更安全,因为可以在编译时而不是运行时发现问题。

泛型通过允许类型具有类型参数来解决此问题:

type Stack(type T) []Tfunc (s Stack(T)) Peek() T {

return s[len(s)-1]

}

func (s *Stack(T)) Pop() {

*s = (*s)[:

len(*s)-1]

}

func (s *Stack(T)) Push(value T) {

*s = 

append(*s, value)

}

这会向 Stack 添加一个类型参数,从而完全不需要 interface{}。现在,当你使用 Peek() 时,返回的值已经是原始类型,并且没有机会返回错误的值类型。这种方式更安全,更容易使用。(译注:就是看起来更丑陋,^-^)

此外,泛型代码通常更易于编译器优化,从而获得更好的性能(以二进制大小为代价)。如果我们对上面的非泛型代码和泛型代码进行基准测试,我们可以看到区别:

type MyObject struct {

int

}

var sink MyObjectfunc BenchmarkGo1(b *testing.B) {

for i := 0; i  b.N; i++ {

var s Stack

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink = s.Peek().(MyObject)

}

}

func BenchmarkGo2(b *testing.B) {

for i := 0; i  b.N; i++ {

var s Stack(MyObject)

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink = s.Peek()

}

}

结果:

BenchmarkGo1BenchmarkGo1-16     12837528         87.0 ns/op       48 B/op        2 allocs/opBenchmarkGo2BenchmarkGo2-16     28406479         41.9 ns/op       24 B/op        2 allocs/op

在这种情况下,我们分配更少的内存,同时泛型的速度是非泛型的两倍。

合约(Contracts)

上面的堆栈示例适用于任何类型。但是,在许多情况下,你需要编写仅适用于具有某些特征的类型的代码。例如,你可能希望堆栈要求类型实现 String() 函数

golang map源码浅析

golang 中 map的实现结构为: 哈希表 + 链表。 其中链表,作用是当发生hash冲突时,拉链法生成的结点。

可以看到, []bmap 是一个hash table, 每一个 bmap是我们常说的“桶”。 经过hash 函数计算出来相同的hash值, 放到相同的桶中。 一个 bmap中可以存放 8个 元素, 如果多出8个,则生成新的结点,尾接到队尾。

以上是只是静态文件 src/runtime/map.go 中的定义。 实际上编译期间会给它加料 ,动态地创建一个新的结构:

上图就是 bmap的内存模型, HOB Hash 指的就是 top hash。 注意到 key 和 value 是各自放在一起的,并不是 key/value/key/value/... 这样的形式。源码里说明这样的好处是在某些情况下可以省略掉 padding 字段,节省内存空间。

每个 bmap设计成 最多只能放 8 个 key-value 对 ,如果有第 9 个 key-value 落入当前的 bmap,那就需要再构建一个 bmap,通过 overflow 指针连接起来。

map创建方法:

我们实际上是通过调用的 makemap ,来创建map的。实际工作只是初始化了hmap中的各种字段,如:设置B的大小, 设置hash 种子 hash 0.

注意 :

makemap 返回是*hmap 指针, 即 map 是引用对象, 对map的操作会影响到结构体内部 。

使用方式

对应的是下面两种方法

map的key的类型,实现了自己的hash 方式。每种类型实现hash函数方式不一样。

key 经过哈希计算后得到hash值,共 64 个 bit 位。 其中后B 个bit位置, 用来定位当前元素落在哪一个桶里, 高8个bit 为当前 hash 值的top hash。 实际上定位key的过程是一个双重循环的过程, 外层循环遍历 所有的overflow, 内层循环遍历 当前bmap 中的 8个元素 。

举例说明: 如果当前 B 的值为 5, 那么buckets 的长度 为 2^5 = 32。假设有个key 经过hash函数计算后,得到的hash结果为:

外层遍历bucket 中的链表

内层循环遍历 bmap中的8个 cell

建议先不看此部分内容,看完后续 修改 map中元素 - 扩容 操作后 再回头看此部分内容。

扩容前的数据:

等量扩容后的数据:

等量扩容后,查找方式和原本相同, 不多做赘述。

两倍扩容后的数据

两倍扩容后,oldbuckets 的元素,可能被分配成了两部分。查找顺序如下:

此处只分析 mapaccess1 ,。 mapaccess2 相比 mapaccess1 多添加了是否找到的bool值, 有兴趣可自行看一下。

使用方式:

步骤如下:

扩容条件 :

扩容的标识 : h.oldbuckets != nil

假设当前定位到了新的buckets的3号桶中,首先会判断oldbuckets中的对应的桶有没有被搬迁过。 如果搬迁过了,不需要看原来的桶了,直接遍历新的buckets的3号桶。

扩容前:

等量扩容结果

双倍扩容会将old buckets上的元素分配到x, y两个部key 1 B == 0 分配到x部分,key 1 B == 1 分配到y部分

注意: 当前只对双倍扩容描述, 等量扩容只是重新填充了一下元素, 相对位置没有改变。

假设当前map 的B == 5,原本元素经过hash函数计算的 hash 值为:

因为双倍扩容之后 B = B + 1,此时B == 6。key 1 B == 1, 即 当前元素rehash到高位,新buckets中 y 部分. 否则 key 1 B == 0 则rehash到低位,即x 部分。

使用方式:

可以看到,每一遍历生成迭代器的时候,会随机选取一个bucket 以及 一个cell开始。 从前往后遍历,再次遍历到起始位置时,遍历完成。

我为什么放弃Go语言

有好几次,当我想起来的时候,总是会问自己:我为什么要放弃Go语言?这个决定是正确的吗?是明智和理性的吗?其实我一直在认真思考这个问题。

开门见山地说,我当初放弃Go语言(golang),就是因为两个“不爽”:第一,对Go语言本身不爽;第二,对Go语言社区里的某些人不爽。毫无疑问,这是非常主观的结论。转载

1.1 不允许左花括号另起一行

1.2 编译器莫名其妙地给行尾加上分号

1.3 极度强调编译速度,不惜放弃本应提供的功能

1.4 错误处理机制太原始

1.5 垃圾回收器(GC)不完善、有重大缺陷

1.6 禁止未使用变量和多余import

1.7 创建对象的方式太多令人纠结

1.8 对象没有构造函数和析构函数

1.9 defer语句的语义设定不甚合理

1.10 许多语言内置设施不支持用户定义的类型

1.11 没有泛型支持,常见数据类型接口丑陋

1.12 实现接口不需要明确声明

1.13 省掉小括号却省不掉花括号

1.14 编译生成的可执行文件尺寸非常大

1.15 不支持动态加载类库


名称栏目:浅论go语言的美好和丑陋 go语言很火吗
URL标题:http://myzitong.com/article/hiohge.html