Go字符串比较,终于有人讲清楚了

本文永久链接 – https://tonybai.com/2022/04/18/inside-go-string-comparison

西娅(Thea)是一个刚刚入门Go语言的妹子程序员,今天她遇到了一个让她“surprise”的问题。下面就是那段让妹子西娅困惑的Go代码:

func main() {
    s1 := "12345"
    s2 := "2"
    fmt.Println(`"12345" > "2":`, s1 > s2) // false

    s3 := "零"
    s4 := "一"
    s5 := "二"

    fmt.Println(`"一" > "零":`, s4 > s3) // false
    fmt.Println(`"二" > "零":`, s5 > s3) // false
    fmt.Println(`"二" > "一":`, s5 > s4) // true
}

在这段关于Go字符串比较的代码中:

  • 为什么表达式”12345″ > “2″的求值结果是false呢?
  • 为什么”一” > “零”和”二” > “零”两个表达式的求值结果都是false呢?
  • 而”二” > “一”的求值结果却又为true呢?

四个结果都让西娅百思不得其解!于是西娅在网络上寻找能为其解惑的Go技术资料。

她网上看到一本名为《Go语言精进之路》的“小黄书”,据说这本书中有有关Go字符串原理与字符串比较的详细讲解。

西娅不经意间瞥见,旁边的同事Tony桌上摆着一本黄色的、厚重的书,这不正是她想看的吗!于是西娅向Tony发出了借书一阅的请求。Tony面对“美女攻势”向来是“每战必败”的,于是西娅顺利地拿到了两卷本的《Go语言精进之路》。借午休时间,西娅花了1.5个小时认真学习了书中有关Go字符串的三个章节:第15节的“了解string实现原理和高效使用”、 第52节的“掌握字符集的原理和字符编码方案间的转换”和第56节的“掌握bytes包和strings包的基本操作”。看完后大呼Wonderful!书中的讲解完全解答了西娅的问题。

此时西娅想起了在《Go语言第一课专栏》的结课语《和你一起迎接Go的黄金十年》中作者关于学习Go语言方法的建议:输出大法!通过输出将学到的知识真正内化为自己的知识,于是西娅将自己对书中内容的理解记录了下来。恰好此时旁边的Tony刚刚从午睡中苏醒过来,西娅决定再为一把人师。Tony就这样被稀里糊涂地拽了过来充当学生:)。

以下是西娅的讲解。


1. Go语言中的字符串类型

字符串类型是现代编程语言中最常使用的数据类型之一。在Go语言的先祖之一C语言当中,字符串类型并没有被显式定义,而是以字符串字面值
常量或以’\0′结尾的字符类型(char)数组来呈现的。

Go语言修复了C语言的这一“缺陷”,原生内置了string类型,统一了对“字符串”的抽象。在Go语言中,无论是字符串常量、字符串变量或是代码中出现的字符串字面量,它们的类型都被统一设置为string

Go的string类型设计充分吸取了C语言字符串设计的经验教训,并结合了其他主流语言在字符串类型设计上的最佳实践,最终为Gopher呈现的string类型具有如下功能特点:

  • string类型的数据是不可变的

即一旦声明了一个string类型的标识符,无论是常量还是变量,该标识符所指代的数据在整个程序的生命周期内便无法被更改。

  • 零值可用

Go string类型支持零值可用的理念。Go字符串无需像C语言中那样考虑结尾’\0′字符,因此其零值为”",长度为0。

  • 获取长度的时间复杂度是O(1)级别

  • 支持各种比较关系操作符:==、!= 、>=、<=、> 和<

鉴于Go string是不可变的,因此如果两个字符串的长度不相同,那么无需比较具体字符串数据,也可以断定两个字符串是不同的;如果长度相
同,则要进一步判断数据指针是否指向同一块底层存储数据。如果相同,则两个字符串是等价的,如果不同,则还需进一步去比对实际的数据内容。至于怎么比较,我接下来会讲。

  • 对非ASCII字符提供原生支持

这一特点就涉及到Go字符串中的字符是什么字符、用什么字符编码的问题了。下面我们就来看看。

2. Go字符串采用的字符集编码

Go语言默认使用Unicode字符集,并采用UTF-8编码方案,Go还提供了rune原生类型来表示Unicode字符。Unicode(万国码/统一码)在1994年发布,它是以收纳人类所有字符为目的的统一字符集。Unicode字符集就是将世界上存在的绝大多数常用字符进行统一排队和编号。比如下面是一个Unicode字符集表的片段:

序号 字符
U+0000 … …
… … … …
U+0031 1
U+0032 2
… … … …
U+4E2D
… … … …
U+4EBA
… … … …
U+56FD
… … … …
U+10FFFF … …

我们看到每个Unicode字符(比如表格里的”1″、”中”等)都有自己的唯一序号,这个序号就叫做字符的码点(code point),Go中的rune类型可用于表示码点。

好了,问题来了!Unicode字符集表格有了,Go是如何在内存中存储这些字符的呢?目前业界有多种存储方案,比如:UTF-32(即4个字节表示每个Unicode字符码点)、UTF-16(使用2个字节或4个字节表示每个Unicode字符码点)以及UTF-8。

UTF-8使用变长度字节对Unicode字符(的码点)进行编码。编码采用的字节数量与Unicode字符在码点表中的序号有关:表示序号(码点)小的字符使用的字节数量就少,表示序号(码点)大的字符使用的字节数量就多

UTF-8编码使用的字节数量从1个到4个不等。前128个与ASCII字符重合的码点(U+0000~U+007F)使用1个字节表示;带变音符号的拉丁文、希腊文、西里尔字母、阿拉伯文等使用2个字节来表示;而东亚文字(包括汉字)使用3个字节表示;其他极少使用的语言的字符则使用4个字节表示。

这样的编码方案是兼容ASCII字符内存表示的,这意味着采用UTF-8方案在内存中表示Unicode字符时,已有的ASCII字符可以被直接当成Unicode字符进行存储和传输,无需做任何改变。相对于UTF-16和UTF-32方案,UTF-8方案的空间利用率也是最高的。并且,utf8解码和编码时,也无需考虑字节序问题。

于是,Go语言使用了Utf8编码方案在内存中存储Unicode字符。

以字符“中”为例,它的码点(序号)为U+4E2D,它在Utf8编码则为“0xE4 0xB8 0xAD”,即在内存中Go实际用三个字节来表示“中”这个Unicode字符。

3. Go字符串比较

上面铺垫了这么些内容,就是为了为字符串比较开道。关于Go字符串比较,Go语言规范中只说了一句话:String values are comparable and ordered, lexically byte-wise。什么意思呢?这句话表达了三个意思:

  • 定性:字符串可比较
  • 定量:字符串是有序的
  • 方法:逐字节

下面我对开篇的例子做逐一说明,首先看下面代码:

s1 := "12345"
s2 := "2"
fmt.Println(`"12345" > "2":`, s1 > s2)

s1和s2两个字符串中的字符都是ASCII字符范畴的,每个字符在内存中的编码都是一个字节。按照Go string比较的原理,我们对s1和s2进行逐字节比较。首先比较s1的第一个字符”1″和s2的第一个字符”2″。字符”2″在内存中的字节为0×32,而字符”1″在内存中的字节为0×31,显然0×32大于0×31,到这里已经比出大小了,程序不会继续对后续的字符进行比对了。这也是为什么s1 > s2这个表达式为false的原因。

如果s2 = “12346″呢?那么按照Go string比较的原理,程序在比较s1和s2的前4个字符时都相等,于是只能由第5个字符来判定两个字符串的大小了,s2的第五个字符”6″显然大于s1的第五个字符”5″,于是当s2=”12346″时,s2是大于s1的。

我们再看看含有汉字的字符串的例子:

s3 := "零"
s4 := "一"
s5 := "二"

fmt.Println(`"一" > "零":`, s4 > s3) // false
fmt.Println(`"二" > "零":`, s5 > s3) // false
fmt.Println(`"二" > "一":`, s5 > s4) // true

为了方便后续说明,我们先把”零”、”一”和”二”这三个汉字的Utf8编码计算出来:

  • “零”的UTF8编码为:0xE9 0x9B 0xB6
  • “一”的UTF8编码为:0xE4 0xB8 0×80
  • “二”的UTF8编码为:0xE4 0xBA 0x8C

我们看到,三个汉字的Utf8编码都是三个字节。

好了接下来,我们先比较s4(“一”)和s3(“零”)。根据Go字符串比较原理,程序对s3和s4做逐字节比较,”零”这个字符的第一个字节为0xE9,而”一”这个字符的第一个字节为0xE4,我们知道0xE9 > 0xE4,于是比较停止,判定:s3 > s4。

同理,s3 > s5。

在比较s4(“一”)和s5(“二”)时,由于它们的第一个字节都是0xE4,于是第二个字节决定了它们的大小,0xBA > 0xB8,所以s5 > s4。

4. Go strings包中的Compare函数

Go标准库在strings包中提供了Compare函数用于对两个字符串做大小比较。但按照Go团队的comment,这个函数存在的意义更多是是为了与bytes包尽量保持API的一致,其自身也是使用原生排序比较操作符实现的:

// $GOROOT/src/strings/compare.go
func Compare(a, b string) int {
    if a == b {
        return 0
    }
    if a < b {
        return -1
    }
    return +1
}

实际应用中,我们很少使用strings.Compare更多的是直接使用排序比较操作符对字符串类型变量进行比较,这样更直观,性能大多数场景也会更高,毕竟少一次函数调用。


“好了以上就是我要讲给你听的,听懂了么”。西娅兴高采烈地对此时已经处于清醒状态的Tony说。

“讲的真好。比我书里讲的还透彻”。Tony一边鼓掌一边微笑着说。“程序员妹子西娅Thea终于把Go字符串比较讲清楚了”。

西娅惊讶!“你的什么书”?

Tony指了指办公桌上的小黄书说:“这书就是我写的啊^_^”。

西娅脸上现出一丝红晕… …。


“Gopher部落”知识星球旨在打造一个精品Go学习和进阶社群!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!2022年,Gopher部落全面改版,将持续分享Go语言与Go应用领域的知识、技巧与实践,并增加诸多互动形式。欢迎大家加入!

img{512x368}
img{512x368}

img{512x368}
img{512x368}
img{512x368}

我爱发短信:企业级短信平台定制开发专家 https://tonybai.com/。smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。2020年4月8日,中国三大电信运营商联合发布《5G消息白皮书》,51短信平台也会全新升级到“51商用消息平台”,全面支持5G RCS消息。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻)归档仓库 – https://github.com/bigwhite/gopherdaily

我的联系方式:

  • 微博:https://weibo.com/bigwhite20xx
  • 微信公众号:iamtonybai
  • 博客:tonybai.com
  • github: https://github.com/bigwhite
  • “Gopher部落”知识星球:https://public.zsxq.com/groups/51284458844544

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

我的姥姥

本文永久链接 – https://tonybai.com/2022/04/05/my-grandma

音容犹在慈祥笑,片片追忆祖孙情。一缕思念寄夜雨,两世重隔眼朦胧。–古相思曲《汉乐府诗》

今天是清明节,是一个缅怀亲人、寄托哀思的日子。

2021年12月27日,我最爱的姥姥在安详的睡梦中永远地离开了我们,无疾而终,享年95岁。

民间将高寿且寿终正寝的老人的丧事称为“喜丧”,但我觉得这只是安慰家人的一种善意的手段罢了。对至亲逝去的悲伤之情,即便是时间这把无情的刻刀也很难彻底抹平。

姥姥的一生平凡亦伟大。平凡之处在于姥姥就是一个普通人,一辈子除了工作就是家庭。前半生辛苦劳作,后半生拉扯孙辈。而姥姥的伟大也孕育在这平凡之中,从人杰地灵的淮扬之地来到白山黑水的东北,从0到1的白手起家建立起了一个大家庭,晚年五世同堂,何其不易。

作为姥姥最喜欢的孙辈,我今天就用脑子中的零星记忆以及近几年四处收集的照片追忆一下从小把我带大的、我最爱的姥姥。

“闯关东”一家人

从照片上的时间可以看出,这是一张1972年拍摄的全家福。上图第一排左起(以我的辈分称呼):老舅、姥姥、姥爷;第二排左起:妈妈、三舅、二舅、大舅、大哥、大舅妈。

姥姥叫王竹英,1927年出生于江苏省扬州市,是一个地地道道的南方妹子。1937年末,扬州被日本鬼子攻陷,城里的老百姓遭了殃。但姥姥一家都活了下来,似乎说明姥姥应该是在乡下,没有受到太大影响。姥姥在家里排行老三,上面有一个姐姐、一个哥哥,下面有一个弟弟和两个妹妹,所以姥姥长大了一些后就开始分担养家的责任,文化课学习基本没有。

姥姥是干活儿的一把好手,什么活儿她都能做得来,并且十分能吃苦,少年时的经历为她在工作后的表现奠定了基础。

十几岁时姥姥就到姥爷家做了童养媳。姥爷家的家境据说还是不错的,姥爷从小就读私塾,啥活儿也不用姥爷做。姥姥比姥爷大两岁,来到姥爷家后就成为了干活儿的主力。姥爷的奶奶是一个严苛的老太太,也正是在这位老太太的严厉“教诲”下,姥姥做事既麻利又漂亮,并学到了那些符合中国传统的所谓规矩。

姥姥和姥爷成亲后,先后生下了大舅、妈妈和二舅。新中国成立后不久,国家从全国抽调有文化的人才支援东北建设,姥爷就是其中之一。姥爷的珠算技能很强,来到东北后被分配到了银行上班。

1953年(据我妈妈回忆),姥姥抱着还在襁褓中的二舅只身赶往东北与姥爷团聚。我猜这可能是姥姥第一次出远门,那时交通不便利,姥姥需要到上海坐船到大连,然后转火车到辽宁海城,路途艰辛可想而知。记得姥姥说过,这次“闯关东”可是一根筷子都没带来,完全的一穷二白。好在那时是计划经济体制,所有住房、物资都是国家/单位分配,于是姥爷姥姥算是在东北安了家。

安顿下来后的第二年,姥姥又回到扬州把大舅和妈妈一起接到东北。而之后的三舅、老舅就是在东北出生的了。

姥姥当时正值壮年,要强的姥姥不想只在家里带娃,于是她也想找份工作,补贴家用。那时正值建国后东北大建设的阶段,各个新建的工厂都在招工。姥姥就应聘到当时的海城市陶瓷一厂。

不过姥姥没有文化,又没有什么拿得出手的工业技能,于是姥姥去了选料车间。什么是选料车间呢?从姥姥的只言片语的描述中我大致猜测,就是搬运大石头并粉碎。姥姥的工作估计就是将大石头砸成小碎石然后送入粉碎机器中。这个工种属于重体力,并且工作环境恶劣,容易患上像矽肺这样的职业病,一般都是壮男才会做的,但姥姥一个柔弱南方妹子居然做了十多年(女性重体力工种45岁退休)。

就这样,姥姥一家开始了在东北小城市的生活!

姥姥是劳模

姥爷支援东北后一直在银行工作,但好景不长。因有一次被同事“陷害”,被扣上了不好的帽子,在那个年代,政治正确才是首要的。于是姥爷被“下放”去了沈阳铁路局的大修段。说白了就是在野外作业维修和养护铁路的。由于姥爷常年在外地作业,虽然不远,多是省内,但每月回来次数有限,家务+照顾孩子的重担就落到了姥姥一个人的肩上。

姥姥不仅是一个极其能吃苦耐劳的女性,又是一个很自律且很要强的人,做事情一丝不苟,并且要尽量做到最好。看过反映那个年代电视剧的人都知道,在国有计划经济下,荣誉高于一切!于是当时各大厂矿均开展班组级的争先进评比活动。姥姥在工作没多久后,就因为自身的优秀素质和吃苦耐劳被选为班组长,姥姥作为组长总是冲在最前面,脏活累活抢着干!所以自从姥姥当了组长后,先进班组就没有旁落过。姥姥每年都被评为先进生产者,后面几年还是鞍山市级的劳模据姥姥回忆,她一共当了13年的组长。而按照我老舅的回忆,那时家里姥姥的奖状贴满墙

工作上的投入也影响了对孩子的照料。姥姥每天一大早就起来生炉子做饭,做好后放在炉子上保温,姥姥不等孩子起床就披星戴月的出门上班了。之所以要这样,是因为家离工厂还有很远的距离,交通不便,所以需要早出门。作为组长,姥姥每天都要第一个上班,最后一个下班。那个年代各大厂矿下班后总是有各种会议要开,这样姥姥往往很晚才能到家。在这样的状态下,家里面基本上就是大孩子带小孩子了。

后来我才知道,妈妈还有一个妹妹(如果活到今天,就是我的二姨),就因为生病后医治不及时导致夭折了。

长大后,我还听过一个关于劳模姥姥的故事,这里也尝试回忆一下。

这个故事发生在举世闻名的1975年2月4日的海城大地震发生之前。海城大地震之所以闻名不是因为震级高(7.3级),而是因为它被认为是人类历史上迄今为止,在正确预测地震的基础上,由官方组织撤离民众,明显降低损失的唯一成功案例。这一点通过我姥姥和舅舅的回忆可以证实。

在地震前两周,各大宣传单位、厂矿就已经通知大家近期会有较大震级的地震,让大家做好预防并储备好各种物资以供震后过渡阶段使用。很多家庭晚上已经不回屋子睡觉了,都在院里或外面胡同里搭帐篷休息。但当时正值农历春节前最冷的时期,很多人折腾几天后都倦怠了,看地震没有发生,就抱着侥幸心理回屋睡了,这也是这次地震导致死亡人员超预期的原因。

就这样,学校停课,工厂基本停工,每天主要就是开会做抗震预案。后期干脆很多人都不上班了,周边有亲戚朋友的人也都投亲靠友去了。姥姥家周边的邻居很多都“逃往”外地了。

当时姥姥家的情况是这样的:姥爷在外地修铁路,二舅在外地当兵,妈妈在外地下乡,大舅已经成家,独立生活,老舅自己回扬州那边了,只有三舅在姥姥身边。姥姥简单做了一些物资准备后仍然每天上班。

听姥姥回忆说,当时有一个厂里领导看到姥姥每天坚持上班,就夸姥姥不愧为厂里的先进工作者和劳模,和普通员工就是不一样。姥姥私下里和我们说:当时不是不想投亲靠友,是在东北真没有什么亲戚和朋友

退休后的带娃生活

小时候,我与姥爷、表姐与两个表妹的合影。很遗憾,我居然没找到我们几个孙辈与姥姥的合影。

姥姥和姥爷的工作都属于重体力,因此退休都很早。退休后,姥爷闲不住,又在市委大院找了份传达室的工作,每天收收报纸,接接电话,自在舒服。姥姥则赋闲在家,恰好孙辈都出生后没多久,于是姥姥又过起了带娃的生活。

我和表姐年龄相仿,成为了姥姥的第一批娃。时代虽不同,但带娃的生活却大体相似,无非是吃喝拉撒睡、玩与教育

先说吃

那个年代物质条件十分匮乏,每个月凭各种粮票、油票、布票领物资,细粮更是少。大人们基本都是吃粗粮。留下的细粮给孩子吃。肉的确是很难吃到。再加上姥姥一家是外来户,没什么亲戚可以帮忙,也没有土地可以种菜养鸡,就是死工资,因此生活的确拮据。

按照我姥的说法,我和表姐是姥姥用大/小米粥就着萝卜咸菜一口一口喂大的。有时候邻居家大婶看到我们俩孩子吃咸菜,还埋怨我姥,生怕我们营养不良。可是姥姥也没有办法,如果有更好的食物,哪能不可着孩子吃呢。那时的家里真没那条件。

后来经济条件逐渐改善了,买东西也不完全靠各种票了,我们饭菜质量也得到了很大改善。我还清晰记得姥姥隔三差五就拎着一个小筐,左手拉着我,右手拉着表姐到市中心最大的菜市场买菜的场景。那时候,各种时令蔬菜都可以买了,猪肉也会偶尔买上一小块儿回来给我们做。

在我们这个大家庭里,姥姥的炒菜和姥爷的面条那是“二绝”,至今无出其右。姥姥的炒菜有着南方人的那种细腻和精致,味道也不会像东北菜那么咸。姥姥做的红烧带鱼和干豆腐卷炖肉简直美味地不得了,至今想起来就会流口水。姥爷也不差,他的猪油葱花手擀面那叫一个香气扑鼻。这么说来,虽然小时候物质条件差,但我和表姐口福还是不差的^_^。

再说玩

那个年代儿童的玩具和物质一样匮乏,我们每天无非就是在各个屋子里过家家,钻进煤棚和柴禾垛里躲猫猫,下雨天玩点泥巴啥的。

后来姥爷通过市委大院的“后门”买到了一台彩色电视机,虽然那时候频道很少,但总归算是有了另外一个娱乐手段。

上了小学后,姥爷不知道从哪弄来了一副麻将牌,闲时打麻将就成为了我们的主要娱乐手段。孩子学东西最快,之后大人们也逐渐学会。姥姥平时没啥爱好,唯独对这麻将十分感兴趣。

大家都喜欢和姥姥、姥爷一起打牌,每次看到姥姥出错牌后后悔的那个样子,我们就都会笑的很开心。

最后说说教育

姥姥没什么文化,但这并不代表姥姥不会教育孩子。姥姥话不多,很少说教,更多是身体力行。而这种方式效果显然会更好。

姥姥对日常举止行为要求很严格,不能乱了规矩。比如说:站有站样,坐有坐样;吃饭时不能说话,手必须扶着碗;不能浪费粮食,盛到碗里的米饭必须吃干净;掉在餐桌上的米粒也要捡起来吃掉。姥姥顶多告诉你一遍,后续姥姥每天都会示范给你看。在姥姥的示范中,我们就潜移默化地学会了这些规矩。这些规矩也伴随姥姥一生,即便在其90多岁高龄时,她吃完的饭碗中绝不会留下一粒饭粒,桌子上掉的饭粒也会吃掉。

姥姥十分爱干净整洁,退休后每天都会把厨房、家里彻底打扫一遍,锅碗瓢盆都亮洁一新。并且,姥姥坚持自己的事情,自己动手做,从不依赖别人。80多岁后,自己的贴身衣物依旧坚持自己清洗,不用儿女帮忙。

姥姥一辈子勤俭节约,从不乱花钱。但如果别人遇到困难,她确认尽全力帮忙。很清晰地记得小时候有两个南方来的尼姑师傅敲门化缘,尼姑师傅没有要求很多,但姥姥坚决把她们请到餐桌上和我们一起吃饭。

在我的印象中,姥姥一辈子也没和周边邻居、工厂同事吵过,和姥姥打过交道的人都说姥姥是好人,甚至有些“傻”。所有别人不愿意做的事情,姥姥都没有怨言的去做好。

姥姥十分重视亲情教育。我们孙子辈每年最期盼的三个日子是姥姥生日、姥爷生日与春节。在这三个日子里,这个大家庭的所有人都会聚在家里吃一顿饭。大人们暂时忘却工作中的烦恼,忙前忙后准备吃食。孩子们更是只剩下玩+吃。姥姥喜欢这种孙男弟女围绕在身边的热闹,在这样的氛围中,所有人都会深切地感受那条连接每一个人的亲情纽带。而孩子们则会在这样的氛围中体会到家的重要性。

正式“退休”后的生活

记忆中,在我小时候,姥姥得过两次脑血栓。好在抢救治疗及时,姥姥都幸运地恢复了健康,只是第二次脑血栓让姥姥的左腿与左臂时常用不上力气,但生活自理没有大问题。

也正是由于这两次大病,姥姥不能再继续她和姥爷的带娃生活了。我和表姐已经长大上小学,我的两个表妹也送去了幼儿园。不过在姥姥的强烈要求下,我每天还是去姥姥家吃午饭(学校就在姥姥家附近,但离我自己家很远),晚上在姥姥家做作业,直到妈妈或爸爸下班来接我。

这样的情况一直持续到小学6年级。姥姥居住的平房区开始动迁改造,姥姥和姥爷也只能搬离老房子。我那时也长大了,中午可以带饭或在学校食堂买饭吃了。姥姥和姥爷这回真正进入了“退休”生活了。

在我上初二的时候,姥姥姥爷家的新楼房建好了,老两口乔迁新居,开始了幸福的晚年生活。此时,二老的子女都已经成家立业,二老又都有退休金和医保,虽然谈不上小康,但足够两个人吃喝不愁,再加上子女都很孝顺,尤其是二舅,每周都给二老买不少生活用品、蔬菜肉食。每周其他子女也都会轮流过来看望父母,我们这些孙子辈的孩子更是喜欢到姥姥家看看两位老人,并陪两位老人打麻将玩扑克。

就这样,二老在新居里度过了他们的金婚和钻石婚,过着幸福的退休生活。

晚年十五载

2006年12月,身体一向硬朗的姥爷被确诊为肝癌晚期,并且癌细胞已经转移全身,无法手术治疗。病魔很快击垮了姥爷,那年的冬天姥爷离开了我们,姥姥姥爷神仙眷侣般的晚年生活戛然而止,姥姥承受了人生中第一次巨大的打击。按照姥姥后来的说法,这是她人生中第一件也是唯一一件伤心事。相伴60多年的老俩口就这样阴阳两隔,短时间内真难以接受。

姥爷去世后,姥姥就搬到二舅家,由二舅一家照顾,帮助姥姥从悲伤中走出来。经过大约一年时间,在这个大家庭的孝顺的氛围中,姥姥渐渐地缓了过来,也知道了后续的人生道路只能由她一人独自走下去。她是这个大家庭的顶梁柱和主心骨,她不能垮下去。

2007年下半年姥姥搬回自己家,为了防止出现意外,每天晚上都有一个子女陪着老人,这样一直持续到2021年12月姥姥过世。姥姥打造了一个尊崇孝道的大家庭,而这个大家庭用孝道之心反哺老人,让老人幸福地度过了这晚年十五载。

姥姥身体开始出现退化信号应该是在2018年左右,那几年每年冬天姥姥都得住一次院,在医院调理一段时间。不过在子女孙辈的无微不至的照顾下,姥姥总能顺利出院!

姥姥真正无法自理是从2020年开始的,90多岁的老人,身体生理技能全面退化,所有活动只能局限在床上了。但在子女无微不至的照料下,尤其是刚刚办理退休的老舅的照料下,姥姥身体保持的很好,到后期甚至出现了“返老还童”的生理现象,比如:居然长出了黑发。

2021年5月假期,我把二宝带到姥姥家,这是姥姥第一次见二宝,也是最后一次。当时留下了这样一张的照片:

2021年国庆黄金周我回家看望姥姥,那也是我最后一次看到姥姥。姥姥在最后一年,很多人都不认识了。但我每次回去,姥姥都能第一时间认出我。

姥姥的口头禅

姥姥是江苏人,操着一口东北人不懂的江苏口音。在东北待了大半辈子,姥姥的口音改善了不少,但很多人还是听不懂姥姥的话。但作为被姥姥从小带大的我,姥姥的每句话我都能听懂,也牢记在心里。

姥姥喜欢称我为大白明,也叫大明。称我表姐为大旭。这也是我们这个大家庭对我们的称呼。记得上小学3年级之后,我每天放学后都会和姥姥打个招呼后,然后自己走回家,姥姥每天都会用朴素而温暖的语言对我说:“大明,靠边走啊,看车啊”。

儿时的记忆中,姥姥有两句南方方言口头禅,一个是“牙kao掉”,意思是再乱说,把你的牙打掉;另外一个就是“贱拿家”,意思是在这里不许破坏规则,要破坏,回自己家破坏。这个口头禅常用在一起打麻将或打扑克时我们耍赖而被姥姥发现时。

姥姥没什么文化,但姥姥也会讲故事,虽然数量有限。姥姥最拿手的“段子”叫“一个屁咯嘣嘣,两个屁裂个缝,三个屁连根倒”。

故事的大致内容是:从前有一个漂亮的姑娘,这个姑娘哪都好,但就是有一个缺点:爱放屁。有一个媒婆不信邪,非要给姑娘介绍婆家。姑娘的父亲十分为难。媒婆说你也别为难,要不你就让我见识一下这位姑娘到底是怎么个爱放屁。姑娘的父亲无奈,只好叫来姑娘给媒婆现场演示一番。姑娘于是开始放屁,一个屁咯嘣嘣(注:估计是把房子震得直响)、两个屁裂个缝(注:旁边的大石头列了一个缝),三个屁连根倒(注:旁边的大树连根倒了)。三个屁放完,媒婆被吓跑了。不过姑娘也由于用力过猛,把屁股弄坏了,于是父亲找了一个补鞋匠又把屁股补好了。

你可能觉得这个故事有些粗俗,但这确是我小时候磨着姥姥,姥姥才给讲的。姥姥用南方方言讲出来别有一番味道,每次都能逗得我们几个孩子哈哈大笑。

时间都去哪了

门前老树长新芽
院里枯木又开花
半生存了好多话
藏进了满头白发
记忆中的小脚丫
肉嘟嘟的小嘴巴
一生把爱交给他
只为那一声爸妈
时间都去哪儿了
还没好好感受年轻就老了
生儿养女一辈子
满脑子都是孩子哭了笑了
时间都去哪儿了
还没好好看看你眼睛就花了
柴米油盐半辈子
转眼就只剩下满脸的皱纹了
记忆中的小脚丫
肉嘟嘟的小嘴巴
一生把爱交给他
只为那一声爸妈
时间都去哪儿了
还没好好感受年轻就老了
生儿养女一辈子
满脑子都是孩子哭了笑了
时间都去哪儿了
还没好好看看你眼睛就花了
柴米油盐半辈子
转眼就只剩下满脸的皱纹了

这是由陈曦作词,董冬冬作曲的歌曲《时间都去哪了》的歌词。陈曦在回忆这首歌词的创作过程时提到:“我从小是被姥姥带大的,20多岁的时候觉得到了应该孝顺她的时候,但她已经没了。人生很多事情都是这么错过的”。

看到这里我的眼睛瞬间就湿润了。姥姥的音容笑貌不断复现在我的脑海中。

恰逢姥姥过世后的第一个清明节,谨以此文追忆与纪念我最爱的姥姥

相信此时此刻,姥姥与姥爷在另一个世界已经团聚,继续他们神仙眷侣般的生活!


如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats