<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[无辄的栈]]></title><description><![CDATA[Zack Wu's Blog]]></description><link>https://www.zackwu.com</link><generator>GatsbyJS</generator><lastBuildDate>Sat, 25 Apr 2026 08:46:05 GMT</lastBuildDate><item><title><![CDATA[二十六岁，长期主义与追星逐月]]></title><description><![CDATA[窗外是南半球盛夏的灿烂阳光，微凉的穿堂风透过纱窗，独对着屏幕与半杯咖啡，此时此刻，我用思考与写作来庆祝生日。]]></description><link>https://www.zackwu.com/posts/2025-11-26-think-long-term-and-work-hard/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2025-11-26-think-long-term-and-work-hard/</guid><pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;窗外是南半球盛夏的灿烂阳光，微凉的穿堂风透过纱窗，独对着屏幕与半杯咖啡，此时此刻，我用思考与写作来庆祝生日。&lt;/p&gt;
&lt;p&gt;一半是懒惰，一半是逃避，去年的我用「&lt;a href=&quot;/posts/2024-10-16-my-first-marathon-sydney-marathon/&quot;&gt;写在人生首马一个月之后&lt;/a&gt;」替代了一年一度的生日博文（甚至发表日期都在生日的几周之外），所以今年的这一篇，目光会远望过去的两年，尝试记录下我在这段时间的所思所感。&lt;/p&gt;
&lt;p&gt;大约在一周前，我参加了神户马拉松并成功 PB；大约在一个半月前，我从前司离职并开始了闲散的失业生活。跑步与工作，占据了我（离职前）生活的大部分，也是我反复思考的课题。&lt;/p&gt;
&lt;h2 id=&quot;跑步&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%B7%91%E6%AD%A5&quot; aria-label=&quot;跑步 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;跑步&lt;/h2&gt;
&lt;p&gt;在 2024 年的悉尼马拉松之后，我这一年的训练与比赛总体上算是令人满意。我参加了世界各地的 5 场马拉松与 1 场半程马拉松，也一次次地提升了我的马拉松最好成绩 —— 从首马的 4 小时 20 分 到最近神户马拉松的 3 小时 04 分，其间有许多值得记录的经历与思考，但这篇文章毕竟不是我的跑步日志，所以摘取其中我印象最为深刻的一些。&lt;/p&gt;
&lt;h3 id=&quot;2024-年新加坡马拉松&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2024-%E5%B9%B4%E6%96%B0%E5%8A%A0%E5%9D%A1%E9%A9%AC%E6%8B%89%E6%9D%BE&quot; aria-label=&quot;2024 年新加坡马拉松 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2024 年新加坡马拉松&lt;/h3&gt;
&lt;p&gt;悉尼马拉松赛后，因为膝盖的伤痛，我并没有太充分的训练，甚至可以说是严重地训练不足，但可惜当时的我对马拉松不够敬畏，反而抱着太多侥幸（毕竟我已经完赛过一次了）。&lt;/p&gt;
&lt;p&gt;为了尽可能避开热带的阳光与高温，新加坡马拉松起跑时间在凌晨四点半。匆匆洗漱出门，在忐忑与兴奋中，我还是站在了起跑线后。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2024-scsm-before-start.webp&quot; alt=&quot;2024 SCSM&quot;&gt;&lt;/p&gt;
&lt;p&gt;不出所料地，尽管我放低了预期与配速，但还是在三十多公里之后，双脚愈发疼痛而难以为继，只能在一步一步的煎熬中，伴着渐渐升高的太阳，慢慢挪向终点。这最后的十多公里，在无所遮蔽而没有观众的高速公路路段，我的痛苦来源于烈日的暴晒与身体的疼痛；而在有志愿者与观众欢呼的 CBD 路段，我想要努力跑起来，却无法抗拒身体的告警，只能苦笑挥手，低头前行。&lt;/p&gt;
&lt;p&gt;我不记得我是如何抵达终点，甚至连完赛时间也记不分明，但我至今依旧可以回忆起那一天的沮丧与无力。&lt;/p&gt;
&lt;h3 id=&quot;2025-年武汉马拉松&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2025-%E5%B9%B4%E6%AD%A6%E6%B1%89%E9%A9%AC%E6%8B%89%E6%9D%BE&quot; aria-label=&quot;2025 年武汉马拉松 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2025 年武汉马拉松&lt;/h3&gt;
&lt;p&gt;这是我第一场「完整跑下来」的马拉松。&lt;/p&gt;
&lt;p&gt;在新加坡马拉松的失利后，我有些不确定自己是否有能力&lt;strong&gt;跑&lt;/strong&gt;完一场马拉松 —— 或许在 42 公里的某一个点，我的身体（也许是膝盖，也许是脚踝，也许是某个我从未预料会有问题的部位）就会迫使我不得不以走代跑。同时，新加坡日复一日的炎热与潮湿，也让我的日常训练不甚轻松：哪怕是训练计划中的「轻松跑」，哪怕我在天亮之前开跑，也常常会越跑越艰难，心率渐渐攀升，体感与轻松分道扬镳。所以，虽然我一直在严格遵守训练计划，但心里始终没有底，不清楚自己究竟跑向何方。&lt;/p&gt;
&lt;p&gt;赛前的几天，在到达武汉之后，见到久违的春天与多年未见的好友，我试探性地在解放公园轻松慢跑，没有看手表上的配速与心率，只觉得格外地愉悦，突然有了许多信心。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-wuhan-jiefang-park-1.webp&quot; alt=&quot;解放公园&quot;&gt;&lt;/p&gt;
&lt;p&gt;赛前的一晚，我对着电脑，思量计算着预期的完赛时间与配速。佳明手表预计我的马拉松最好成绩会是 3 小时 45 分左右。相较于悉尼马拉松的成绩，这已然是不小的提升，而且我平时也鲜有跑到这样的速度。习惯性地把这个问题抛给 ChatGPT，在一番对谈之后，它也认为 3:45 是一个合理的目标。然而，回想着自己这几个月的持之以恒，感受着武汉相对怡人的天气，内心深处的一个声音有所不甘：或许，我应该目标更加激进一些。反复权衡，既担心 30 公里后的未知状况，又希望可以跑出自己的最好状态，最终决定用「负分割」（即，前半程留有余力，后半程全力以赴，配速渐渐加快）的战略去面对次日的比赛。&lt;/p&gt;
&lt;p&gt;有一种说法，一场完美的马拉松应当由三部分组成：30 公里左右前的游刃有余，30 - 35 公里左右的愈发艰难，以及最后几公里的竭尽所能「顶住」。以此概述我的武汉马拉松，恰如其分。&lt;/p&gt;
&lt;p&gt;起跑之后，我按照计划中的配速稳定巡航，心无旁骛地感受着身体的反馈，如今回想起来，沿途的风景与路旁围观群众的呐喊是我对武汉马拉松的背景记忆。抵达半程，计时器上的时间告诉我一切尚在掌握，同时身体的疲劳程度依旧可控，所以，按照赛前的打算，我决定渐渐加速。一路到 30 公里之后，疲惫渐渐累积，但心算时间，我对 3:45 内&lt;strong&gt;跑&lt;/strong&gt;完已然有了十足的信心，心情也越来越放松。&lt;/p&gt;
&lt;p&gt;可我还想要更多，我想要尽我所能去追星逐月。我继续加速，同时边跑边与身旁的跑者交流 —— 探问对方的目标与状态，直到找到了一位目标是 3:30 的大哥，他告诉我需要加到的配速，也愿意带我跟着他一路跑到终点。剩下的里程，体感愈发艰难，逐渐逼近快要不行了的边缘，我目光一直锁定着这位陌生跑友的背影，靠着他的带领与鼓劲，我咬着牙，有意识地与无意识地，想着这几个月训练的各种碎片，闷热但瑰丽的日出印象，热带雨中的树丛摇曳，&lt;a href=&quot;https://railcorridor.nparks.gov.sg/visit-rail-corridor/&quot;&gt;Rail Corridor&lt;/a&gt; 散步的野鸡与松鼠，晚餐的羽衣甘蓝沙拉与蓝莓酸奶碗…… 终点前一两公里，我还是跟丢了这位陌生跑友，所以有些遗憾，没有办法在结束后向他道谢。但不管怎样，我快速瞟了一眼手表上的时间与距离，漱最后一口的运动饮料，就这样在 3:29 冲到了终点线。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-wuhan-marathon-medal.webp&quot; alt=&quot;武汉马拉松奖牌&quot;&gt;&lt;/p&gt;
&lt;p&gt;难以用言语描述我在终点的感受。是全部力量耗尽连完整的句子也说不出的绝对疲惫，是紧绷了 42 公里的弦终于松开的如释重负，也是仿佛自己完成了一件天大的成就的狂喜。缓缓挪着双腿，随着人群一步一步向前，有些麻木地接过志愿者递上的奖牌与赛后补给，听着一声一声的「恭喜完赛」，又好像觉得不太真确 —— 我真的跑完了武汉马拉松？我真的达成了 3:29 的 PB？最后的最后，人流的尽头，接驳车把大家都带走。龇牙咧嘴地抬起酸痛的腿上车，或拎或背着这一袋赛后物资，各有各的下一站。&lt;/p&gt;
&lt;h3 id=&quot;黄金海岸悉尼神户&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%BB%84%E9%87%91%E6%B5%B7%E5%B2%B8%E6%82%89%E5%B0%BC%E7%A5%9E%E6%88%B7&quot; aria-label=&quot;黄金海岸悉尼神户 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;黄金海岸、悉尼、神户&lt;/h3&gt;
&lt;p&gt;在黄金海岸与神户，依旧是全力以赴，依旧是追星逐月地从 3:29 到 3:13，再从 3:13 到 3:04。这两场比赛，在对成绩的追求上和武汉有些相似，但是又有许多值得记述的独特回忆，或许以后会有更合适的分享时机。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-gold-coast-marathon.webp&quot; alt=&quot;黄金海岸马拉松参赛照片&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-gold-coast-marathon-medal.webp&quot; alt=&quot;黄金海岸马拉松奖牌&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-kobe-marathon-stone.webp&quot; alt=&quot;神户马拉松 - 日本马拉松诞生地&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-kobe-marathon-medal.webp&quot; alt=&quot;神户马拉松奖牌&quot;&gt;&lt;/p&gt;
&lt;p&gt;而在悉尼，一年之后故地重游。赛前并没有任何的成绩目标，只是计划了轻松随意的配速，最终 3:32 完赛。相比一年前的首马，心态上如同一场郊游，体感上也轻松数倍，所以，这真真切切地证明了：我这一年的训练让我有了很大的提升。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-sydney-marathon-photo.webp&quot; alt=&quot;悉尼马拉松参赛照片&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2025-sydney-marathon-medal.webp&quot; alt=&quot;悉尼马拉松奖牌&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;训练与思考&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%AE%AD%E7%BB%83%E4%B8%8E%E6%80%9D%E8%80%83&quot; aria-label=&quot;训练与思考 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;训练与思考&lt;/h3&gt;
&lt;p&gt;其实训练本身不过是日复一日的重复与缓慢提升。回看昨天的训练，上周的训练，甚至上个月的训练，都很难觉察出明显的不同；但不知不觉中，一年过去，比照一年前的自己，每次训练的距离和配速都显著地提升了。&lt;/p&gt;
&lt;p&gt;或许所有的变化都发生在不经意的间隙中，我需要做的，不过是坚持跑下去。这一年，不论是出差还是旅行，我的行李箱里始终有一双跑鞋，也尽量严格地遵守了我的训练计划。在某个突然意识到自己进步的瞬间，我在 Threads 上&lt;a href=&quot;https://www.threads.com/@izackwu/post/DGFkN9Xx8P2&quot;&gt;写道&lt;/a&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;从准备第一场马拉松开始，陆陆续续训练了大半年，期间各种小伤小病而时不时停跑，但大体还算是坚持下来。一直觉得自己跑得没啥进步，六分配跑超过半小时后心率就渐渐失控往上涨，绝对速度也快不起来。当然这有新加坡的天气因素，但正如大家说，强者不抱怨环境，新加坡也有跑步很厉害的人。所以对自我的认知一向不敢自信，只能说「一直还在跑着」。&lt;/p&gt;
 &lt;br /&gt;
&lt;p&gt;但上周的一次跑步，第一次跑到 Rail Corridor，在下过雨的清晨湿润中，跑着和往常一样的配速，出乎意料地感觉到了「轻松」，以及越跑越舒爽的跑者愉悦 runner’s high。在那一瞬间，怀疑了手表 GPS，怀疑了自己的感受，才犹豫着接受了这突然而来的进步。那一天发生了什么呢？除了在一个新的路线上跑步，一切都不过如常。&lt;/p&gt;
 &lt;br /&gt;
&lt;p&gt;在接下来的一个礼拜，我换了不同的跑步路线，也尝试了轻松跑、渐加速跑，但惊喜的是，这种「轻松」的感觉一直没有消退，RQ 的即时跑力也确认了我的进步。&lt;/p&gt;
 &lt;br /&gt;
&lt;p&gt;我不理解这突然的进步，但我很开心。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;值得一提的是，这一年我关注了不少跑步相关的博主。他们大部分时候是我闲暇的陪伴，但我也常常因为他们的观点和行动而深受触动。直接摘录我今年 5 月份在 Threads 上的一条&lt;a href=&quot;https://www.threads.com/@izackwu/post/DJLEnsFTUN2&quot;&gt;推文&lt;/a&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;膝盖不适，几乎没法跑步的一周，反而思考了更多关于跑步的事情。&lt;/p&gt;
 &lt;/br&gt;
&lt;p&gt;跑步的某些时刻是需要一点点信念感的，比如受伤停跑的沮丧，又比如马拉松最后的几公里。&lt;/p&gt;
 &lt;/br&gt;
&lt;p&gt;基普乔格在破二努力中说出的那句话，No human is limited，曾经一度给我很多力量，但仿佛又始终有一些不太真实的疏离感：我一个业余跑者，怎么会没有上限呢？我没法跑那么快，也没法跑那么多。&lt;/p&gt;
 &lt;/br&gt;
&lt;p&gt;后来，无意中发现了一位精英跑者的频道（&lt;a href=&quot;https://www.youtube.com/c/PhilyBowden&quot;&gt;philybowden&lt;/a&gt;），从她那里学到了一种新的态度：Love the grind。自然，比赛日的狂欢，个人极限的突破，这些高光时刻让人振奋。但更多的时候，跑步就是日复一日的「磨」，在外人（以及某些时刻的自己）看来，相当琐碎无聊，还要时不时面对伤病的困扰。可是，要想长久的跑下去，就需要学会接受、享受这种日常。&lt;/p&gt;
 &lt;/br&gt;
&lt;p&gt;又想到我认可的其他跑步博主。&lt;a href=&quot;https://www.youtube.com/@shadow-runner&quot;&gt;黑影儿TV&lt;/a&gt;，作为相对接近普通人的跑者，风雨无阻地跑了这么多年，成绩一点一点地进步，我觉得这或许是我将来的一种可能性。&lt;a href=&quot;https://www.youtube.com/@MarathonRunning&quot;&gt;山雨小月&lt;/a&gt;在关于波士顿马拉松的视频中提到，波马是对跑者多年努力的一种奖励，就像餐后的甜点一样（仅凭记忆复述）。我希望我能有站在波马起点的那一天。&lt;/p&gt;
 &lt;/br&gt;
&lt;p&gt;写完才想起来，其实还有一位跑者（&lt;a href=&quot;https://space.bilibili.com/382431725&quot;&gt;世杰Ski&lt;/a&gt;）的态度我也觉得很有道理，「只争朝夕的长期主义者」，尤其是他最近关于成绩和伤病的思考。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;现在我的想法大体上依旧，额外的是，在这条推文之后，偶然听到了「信口开合」播客采访李犁教练的一期节目&lt;a href=&quot;https://podcasts.apple.com/hk/podcast/%E6%97%A0%E4%BC%A4%E8%B7%91%E5%88%B0%E8%80%81-%E9%87%91%E7%89%8C%E6%95%99%E7%BB%83%E7%9A%84%E9%95%BF%E6%9C%9F%E4%B8%BB%E4%B9%89-s3e10/id1765711807&quot;&gt;《无伤跑到老：金牌教练的长期主义》&lt;/a&gt;，加之上文提到的&lt;a href=&quot;https://www.youtube.com/@shadow-runner&quot;&gt;黑影儿TV&lt;/a&gt;对其的推崇与个人解读，我也渐渐理解并相信了跑步的「长期主义」。&lt;/p&gt;
&lt;p&gt;从我认真跑步开始，其实也不过一两年，所以于我而言，一切不过是长期跑步的开端。想到这，既觉得安心从容，又对自己充满了信心。&lt;/p&gt;
&lt;h2 id=&quot;工作&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%B7%A5%E4%BD%9C&quot; aria-label=&quot;工作 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;工作&lt;/h2&gt;
&lt;p&gt;作为一个普通的上班族，无可避免的，工作占据了睡眠时间之外的绝大部分。&lt;/p&gt;
&lt;p&gt;如果直面内心，去年的我之所以跳过了生日博文，其中的主要原因大概是对工作的不知从何表述。而在此刻，从前司离开一个半月有余，或许站在一定的距离之外，可以更加平静地来回顾这两年多的工作。&lt;/p&gt;
&lt;p&gt;在两年前的&lt;a href=&quot;/posts/2023-12-03-a-year-of-change/&quot;&gt;生日博文&lt;/a&gt;中，我其实已经描述了工作的内容与环境，以及我的大体感受。简单概括的话，这是一份量化交易公司的岗位，但是并不直接与交易打交道，而是相当标准的软件工程岗位。工作环境与文化非常好，绝大多数同事都有优秀的背景和能力，日常的工作沟通友好而高效。在&lt;strong&gt;工作时间上&lt;/strong&gt;可以做到很好的 WLB，不用担心加班，同时薪酬也高于市场水平。我使用一门小众的函数式语言 OCaml，维护内部的一些工具，组内的其他同事大多位于全球的其他办公室。&lt;/p&gt;
&lt;p&gt;基于这样的描述，我似乎找不到任何离开的理由，但是在过去的几个月，我对工作渐渐失去了热情，直至最终无以为继。&lt;/p&gt;
&lt;p&gt;我反复思考其中的原因：有一些其实是工作无关的个人事务，有一些是工作中过于具体而不便公开讨论的事项（不论是签署的保密协议还是简单的职业素养），剩下的一些理由或许听上去有些大而空泛，但确是我真实的感受。&lt;/p&gt;
&lt;h3 id=&quot;价值感&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BB%B7%E5%80%BC%E6%84%9F&quot; aria-label=&quot;价值感 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;价值感&lt;/h3&gt;
&lt;p&gt;我曾经一度相信：工作本身不需要有意义，只要能 WLB 且挣到足够的薪水，在工作之外做喜欢的事情追求意义即可。&lt;/p&gt;
&lt;p&gt;我很难说这种观念是否正确，但在现在的我看来，它至少并不适用于所有人，也不 100% 适用于我。&lt;/p&gt;
&lt;p&gt;在一家金融公司做内部系统，一切都在公司的高墙之内。从微观来看，其实这和维护其他系统（比如开源项目，比如大公司 APP）并没有太大的差别，日常面对的也无非是具体的任务和一行行的代码，也有各自的技术挑战；但如果从其中抽离，以一个非程序员的外部视角，审视自己所做的一切，便慢慢感觉到了局限 —— 我工作的好与坏，只会影响到少量的内部用户和公司的营收，当然，还有我的年终奖。后面两个数字的变化可大可小，但它们只会偶尔（一年一度地）出现在我的面前，很难让我直观上建立起不论正面或负面的反馈。&lt;/p&gt;
&lt;p&gt;这一点或许是所有大公司程序员所面对的共同处境：身处一个庞大的机器中，自己所掌控的不过是一个螺丝、一把扳手。但相较于科技行业，金融行业整体更加封闭，似乎每一家公司都在自己的堡垒内悄悄建设着什么宏伟而精密的秘密武器，也许是闭门造车，也许是掌握了独家秘笈，但总之是为了在与彼此的军备竞赛中占据上风。这是一个零和游戏吗？在科技行业如日中天的那些年，雄心勃勃的创业者常说自己所写的代码可以「改变世界」。这或许有些夸大其辞，但如果自己所做的事至少可以影响到公司之外的一些人，会不会有一种「被看见」的意义感呢？&lt;/p&gt;
&lt;p&gt;当然，比较公平地说，在我工作的绝大部分时间，我并不会因此感到困扰 —— 前司在华尔街金融公司中已然是最注重工程师文化的一家（至少是「之一」），而且我也十分认可前司大多数同事的技术能力和工程实践，工作体验其实相当不错（我相信优于不少科技公司的组）。可是，当我因为其他原因的叠加而对工作产生倦怠的苗头时，价值感的缺失让我难以找到意义的锚点，从而越漂越远，直至看不见这艘船。&lt;/p&gt;
&lt;p&gt;巧合的是，最近看到了 laike9m 的一篇&lt;a href=&quot;https://x.com/laike9m_/status/1963485134109479090&quot;&gt;推文&lt;/a&gt;，虽然和我的出发点截然不同，但似乎抵达了相似的心境。&lt;/p&gt;
&lt;h3 id=&quot;职业发展&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%81%8C%E4%B8%9A%E5%8F%91%E5%B1%95&quot; aria-label=&quot;职业发展 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;职业发展&lt;/h3&gt;
&lt;p&gt;也许价值感有些过于虚无缥缈，那么具体一些，职业发展也是我反复思考而没有满意答案的问题，尤其是在这个 LLM 大有「替代程序员」的势头的时代。&lt;/p&gt;
&lt;p&gt;在两年前的&lt;a href=&quot;/posts/2023-12-03-a-year-of-change/&quot;&gt;生日博文&lt;/a&gt;中，我写道：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;但从公司整体的技术栈来说，和互联网公司追求（或者发明）时新技术的思路不同，我司在很多方面依旧使用着相当「传统」的技术，比如，没有使用 Docker/Kubernetes 之类的云原生方案，而是部署到具体的物理机或虚拟机。但在一开始的惊讶和不适应之后，我也渐渐理解了这些背后的原因。我相信，不论使用何种框架或者工具，作为软件工程师，最核心的技术能力都是相通的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我依旧相信软件工程师的核心能力不是对某一门语言、某一项技术的熟悉程度，而且在前司的这两年半有余，不骄不馁，我自认为我的许多能力也确实得到了显著的提升，比如人际沟通与处理项目的复杂度，所以我并不遗憾。但是一直使用一门极其冷门小众的语言（OCaml），几乎只与内部的系统和项目打交道，我也时不时会觉得有些隐隐地不安 —— 我是不是「点歪了科技树」？如果我现在需要去找一份新的工作，我有多大的信心可以找到令我满意的？抛开公司的光环与平台杠杆，作为一个软件工程师，我现在能做成什么？&lt;/p&gt;
&lt;p&gt;我不知道。实话说，这些焦虑在我入职的新鲜劲过了之后其实就若隐若现了，我也好几次和公司内较为资深的同事探讨（包括在加入公司前的面试问答中），没有人能给出完全令人信服的答案，但每个人似乎又都能找到一些很有道理的解释 —— 譬如上面引文中我自己的解释。&lt;/p&gt;
&lt;p&gt;而 LLM 时代的开启，又让这个问题更加难以回答一些了。假如 LLM 可以写好每一门（流行的）语言，用好每一个框架，那对于一个人类软件工程师而言，似乎对语言和框架的熟识也没有那么重要了，反而应该尽量发挥自身更为抽象更为高层的能力，或许是系统设计，或许是与其他人类的沟通，又或许是 LLM 尚未学到的 domain knowledge 和难以用文字传述的 knowhow。就我自身经验而言，我对现代前端只有入门水平，但是在简单学会使用 LLM 和相关工具之后，我便可以做出之前难以想象的前端页面，比如记录我马拉松参赛的 &lt;a href=&quot;https://run.zackwu.com/&quot;&gt;run.zackwu.com&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;既然如此，我的焦虑似乎应该减少？&lt;/p&gt;
&lt;p&gt;也许是 FoMo，也许是面对一个黑盒的不安，也许是更深层次的存在危机，也许只是纯粹是想要理解自己所用的工具，我时不时会焦虑于 LLM 的日新月异。成为一个精通 LLM 的&lt;strong&gt;使用&lt;/strong&gt;的软件工程师，或许并不是我想象中的职业发展。&lt;/p&gt;
&lt;p&gt;又回到现实的考量。市场上为数不多依旧在招聘的公司，大多数也依旧对于软件工程师有着具体的期许和技术匹配要求，有些甚至在岗位名称上都会冠以某某语言工程师。所以回到我一开始自问的几个问题，我有信心在一定的准备之后找到新的工作，但是如果直接面对当下的求职市场，我并不能轻松地自我证明我的能力和价值。&lt;/p&gt;
&lt;p&gt;在我内心深处，有时候有这样一条模糊的逻辑：如果我不会在这家公司一辈子工作下去，如果在这家公司的工作并不会让我在寻求下一份工作更有竞争力，甚至某种意义上限制了我的竞争力，也许待得越久越难以做出离开的决定。&lt;/p&gt;
&lt;h3 id=&quot;职业生涯很长&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%81%8C%E4%B8%9A%E7%94%9F%E6%B6%AF%E5%BE%88%E9%95%BF&quot; aria-label=&quot;职业生涯很长 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;职业生涯很长……&lt;/h3&gt;
&lt;p&gt;我一直都知道并相信，职业生涯很长，我现在不过是刚过起点。但在日复一日的工作与生活之间，诚实面对自己，怀疑的念头又时不时会浮起。&lt;/p&gt;
&lt;p&gt;如同跑步一样，虽然我暂时还不知道自己最终会跑到怎样的水平，但我选择说服自己相信长期主义。我离开前司或许是一个明智的选择，或许是一个将来会后悔的错误，但至少现在的我是解脱而放松的，在长远的职业生涯中，我容许自己犯错误和休息。&lt;/p&gt;
&lt;p&gt;至于下一步何去何从，那便是需要我去认真思考的下一个问题（也欢迎读到这里的朋友们指点）。长期主义的另一面，是下定决心之后的追星逐月。&lt;/p&gt;
&lt;h2 id=&quot;最后&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9C%80%E5%90%8E&quot; aria-label=&quot;最后 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;最后&lt;/h2&gt;
&lt;p&gt;在开始写这篇文章的时候，脑中只有几个非常模糊的关键词：跑步，工作，长期主义，追星逐月。从晨跑后写到日落，其间穿插着几场汹涌的偶阵雨和我时不时的「摸鱼」，最终也零零碎碎写了这么长（其实我早该写一写其中的一些内容了，而不是留到今天）。&lt;/p&gt;
&lt;p&gt;我对许多问题还没有想清楚，或许还在怀疑，或许还在摇摆，又或许在错误的方向一路狂奔，但毕竟二十六年我出生在这一天，所以就当这是一次对不成熟观点的 coredump 吧，留待之后的文章引用评述。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[写在人生首马一个月之后]]></title><description><![CDATA[一个月前，我（大体）顺利地完成了人生中的第一场马拉松，悉尼马拉松。赛前与赛后，种种感受，回顾我的跑步历程。]]></description><link>https://www.zackwu.com/posts/2024-10-16-my-first-marathon-sydney-marathon/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2024-10-16-my-first-marathon-sydney-marathon/</guid><pubDate>Wed, 16 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;其实小时候的我并不喜欢跑步，也不喜欢运动。&lt;/p&gt;
&lt;p&gt;我至今记得初中时候，体育课上跑了几圈之后的我，眼前的世界蒙上一层仿佛窒息的白雾，脑中只剩下零星的小黑点乱飞。那时候的我，尤其是在读了《红楼梦》之后，暗暗在心中将自己与林黛玉相对照，甚至带着一点小小的骄傲，认为自己的体弱是某种天妒英才的必然。&lt;/p&gt;
&lt;p&gt;所以现在想想也有些奇妙，我后来居然喜欢上了跑步，甚至完成了一场 42.195 公里的马拉松。这一切都是怎么发生的呢？&lt;/p&gt;
&lt;p&gt;今天，距离悉尼马拉松已经过去了一个月，赛后的兴奋与疼痛似乎也快要消散。正好有些空闲，回顾我的跑步历程，复盘人生第一场马拉松。&lt;/p&gt;
&lt;h2 id=&quot;开始跑步&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%BC%80%E5%A7%8B%E8%B7%91%E6%AD%A5&quot; aria-label=&quot;开始跑步 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;开始跑步&lt;/h2&gt;
&lt;p&gt;接上文，初中的我害怕跑步后的痛苦感受，所以在和老师申请之后，避开了所有体育课上的跑步内容。&lt;/p&gt;
&lt;p&gt;直到高中时候，某个无甚特别的晚自修间歇，或许是阅读并相信了跑步的益处，或许是意识到了身体健康（对学习成绩）的重要作用，或许是觉得运动可以释放学业的压力，又或许只是单纯想去散散步吹吹风，我下楼来到了操场，慢跑了两圈， 800 米。我不记得当时有没有什么特别的感受，也不记得自己是如何决定的，但自此之后，几乎每晚我都会去操场上独自奔跑，一直到高考前的那一夜。&lt;/p&gt;
&lt;p&gt;大学时期，应该和很多国内的大学类似，我所在的学校要求学生每学期完成一定量的跑步（大概是 80 公里？）。很多同学对此十分不开心，但我乐在其中，甚至偶尔还会帮室友刷一刷跑量。从宿舍楼下出发，穿过宿舍楼群，穿过桥洞，一路跑到南区体育场，然后一圈一圈地慢慢跑着，结束后去体育场旁边的教育超市买一瓶鲜奶或者酸奶，一边喝一边吹着风慢慢走回宿舍。&lt;/p&gt;
&lt;p&gt;印象比较深刻的一次，和室友一起跑步，我们讨论着即将到来的上海马拉松。我们学校每年会派出很多学生去上马做志愿者，因为可以加素质拓展分，所以报名者甚多，需要通过志愿者协会的面试才有资格。我和他对于这样的事情是没有什么兴趣的，尤其是掺杂了加素质拓展分的「功利」因素，我对此甚至有些嗤之以鼻。但不论如何，那是我第一次意识到身边的马拉松赛事，也开始思考我的跑步：当时的我不在乎配速，不在乎距离，也不在乎跑量，只是随意地跑着，每次也只能跑不到 5 公里，但参加马拉松的想法依旧让我感到兴奋。我畅想着，假如我每个月可以进步 1 公里，那么只需要一年多，我就可以从 5 公里增加到半程马拉松的距离，参加明年的上海马拉松（我并不知道上马没有半马），再过一年就可以参加全程马拉松。&lt;/p&gt;
&lt;p&gt;马拉松训练当然没有那么容易，后来的我也渐渐淡忘了这个目标，疫情封控更是让毕业前参加上马的想法彻底泡汤。&lt;/p&gt;
&lt;h2 id=&quot;半马&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8D%8A%E9%A9%AC&quot; aria-label=&quot;半马 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;半马&lt;/h2&gt;
&lt;p&gt;毕业后，我来到了新加坡。热带的湿热让跑步变得愈加艰难，但我依旧是慢慢跑着，在健身房的跑步机上，在路边的人行道上。&lt;/p&gt;
&lt;p&gt;直到 2022 年的某一天，我在某处看到了新加坡马拉松的报名信息，自我评估之后，报名了半程马拉松。21 公里的距离，让我开始有些严肃地对待跑步，于是，跟着 Nike Run Club 的半马训练计划，我一步步地增加我的跑量和速度，充满期待地准备首次半马。&lt;/p&gt;
&lt;p&gt;然而天不遂人愿，赛前的几个月，在跑完一次超过 10 公里的「长距离」之后，我突然觉得心脏部位有些不适。就医并未检查出任何问题，但是心脏的不适感让我有些畏缩，渐渐地降低了训练强度。就这样一直到了比赛前几天，我再次咨询了医生，得到了可以正常参加半马的评估，终于下定决定。&lt;/p&gt;
&lt;p&gt;作为第一次半马，如今回顾来看，新加坡马拉松或许并不是一个很好的选择：四点半天没亮起跑，比赛日当天下暴雨，沿路没有观众，如此等等。但当时的我，怀揣着对心脏健康的惴惴不安，依旧是无比激动地跑完了半马，拿到了第一块跑步赛事的&lt;a href=&quot;https://twitter.com/_zackwu/status/1599324898270511104/&quot;&gt;奖牌&lt;/a&gt;。至于所谓的心脏不适感，后来也确认是我当时服用的某种药物所导致的错觉，并没有任何实质问题。&lt;/p&gt;
&lt;p&gt;如同打开了新世界的大门，在此之后，我一连报名了好几场半马比赛：黄金海岸，墨尔本，以及港珠澳大桥。&lt;/p&gt;
&lt;h2 id=&quot;伤痛&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BC%A4%E7%97%9B&quot; aria-label=&quot;伤痛 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;伤痛&lt;/h2&gt;
&lt;p&gt;有人说，第一场比赛之后的兴奋期是新手跑者最容易受伤的时期，缺乏经验但又充满了太多热情。正是如此。&lt;/p&gt;
&lt;p&gt;在跑完黄金海岸的半马之后，没有充分休息和恢复，我第二天又参加了 10 公里。当时便感觉格外吃力，却没有意料到，这将会导致我的第一次跑步伤痛，跟腱炎。&lt;/p&gt;
&lt;p&gt;一开始的我对此不以为意，只是休息了几天，依旧坚持跑步，甚至还强行参加了之后的墨尔本和港珠澳大桥半马。因为伤痛，这两场比赛前我并没有很充分的准备，比赛当天也只能是忍着痛跑完，并没有很好的成绩。&lt;/p&gt;
&lt;p&gt;几个月后，跟腱炎依旧不见好转。我渐渐意识到，或许，我需要认真面对伤痛，而不应该急着去跑更多的赛事。于是取消了近期的好几场赛事，包括原定为首马的新加坡马拉松。去看医生，接受治疗，每天坚持做康复训练，抑制住跑步的热情，停跑了一段时间。&lt;/p&gt;
&lt;h2 id=&quot;全马&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%85%A8%E9%A9%AC&quot; aria-label=&quot;全马 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;全马&lt;/h2&gt;
&lt;h3 id=&quot;训练&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%AE%AD%E7%BB%83&quot; aria-label=&quot;训练 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;训练&lt;/h3&gt;
&lt;p&gt;随着跟腱炎慢慢好转，我又重新开始规划起下一场比赛，但不同的是，我不再像之前那样冒进，而是决定从零开始，认真训练，为第一场马拉松做充分的准备。考虑到悉尼马拉松即将加入大满贯的传闻，加上地理位置的便利，我最终选择了悉尼马拉松。&lt;/p&gt;
&lt;p&gt;因为之前受伤的教训，这次训练我使用了一个 AI 跑步教练，&lt;a href=&quot;https://trainasone.com/&quot;&gt;TrainASOne&lt;/a&gt;，并且十分谨慎地逐步增加跑量和强度。许多跑者应该都听说过 run slow to run fast 的理念，但有时候我依旧会自我怀疑，我都已经跑步这么多年了，真的有必要 9 分配（每公里 9 分钟的速度）甚至 10 分配慢跑吗？这时候便需要一点信念，相信 TrainASOne 避免受伤的理念，说服自己以非常慢的速度渐进。&lt;/p&gt;
&lt;p&gt;另一方面，为了严格遵守训练计划，我从原本的夜跑，改成了早起跑步。我从未预料过我会是一个能够早起的人，并且在我人生的某些重要早晨，我曾不止一次地睡过头。但是为了马拉松，我居然做到了每天六点起床，在天还未亮（新加坡常年七点日出）的时候出门跑步。看着天色越来越亮，城市逐渐苏醒，晨跑让我享受到了一种从未有过的自由，有一种「我在一大早就已经完成了训练计划」的满足感。&lt;/p&gt;
&lt;p&gt;就这样，日复一日，训练了小半年，虽然我每次都觉得今天的自己和昨天没有什么区别，但我渐渐可以跑得更远，更快，也更加轻松。我想，这次我应该准备充分了。&lt;/p&gt;
&lt;h3 id=&quot;比赛&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%AF%94%E8%B5%9B&quot; aria-label=&quot;比赛 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;比赛&lt;/h3&gt;
&lt;p&gt;比赛当天，一大早起床出门，按照脑海里预演过的流程，前往起点，开始跑步。&lt;/p&gt;
&lt;p&gt;天气比预计的要凉快一些，风也更大一些，但悉尼马拉松的赛道和预期一样多坡，全程有不少爬升。前 35 公里的我虽然对于反复上下坡有些烦恼，但是倒也轻松自如，按照预定的配速稳定跑着，心里计算着大概的完赛时间。然而到了 35 公里之后，脚上渐渐有些疼痛，爬坡也开始有些吃力了，中途走走停停了几个坡，一直到最后终点前的下坡冲刺，终于勉强在 4:20 的尾巴上完赛。&lt;/p&gt;
&lt;p&gt;回忆这 42 公里多，路线和沿途的风景已然有些记不清了，但围观群众的热情、跑者的氛围让我难忘。在泠冽的晨风中，和数万人一同奔跑在悉尼的街道上，听着路边无数陌生人的欢呼，这比起日常一个人枯燥的训练，实在是再棒不过了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2024-sydney-marathon-medal.webp&quot; alt=&quot;2024 悉尼马拉松奖牌&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;赛后伤痛&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%B5%9B%E5%90%8E%E4%BC%A4%E7%97%9B&quot; aria-label=&quot;赛后伤痛 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;赛后/伤痛&lt;/h3&gt;
&lt;p&gt;这次马拉松，我自认为赛前准备相当充分，可惜在赛后又疏忽了。&lt;/p&gt;
&lt;p&gt;静休了两天之后，自我感觉大腿的酸痛似乎已经过去，便开始了下一趟旅行，殊不知我的身体其实还很劳累。因此，在旅途的奔波和游山玩水的远足之后，我的膝盖开始隐隐作痛。&lt;/p&gt;
&lt;p&gt;在旅途中一个陌生的小镇，早晨的我出门慢跑，却第一次因为膝盖疼痛而没法继续，只能给女友打电话来接我，一瘸一拐地走去会合地点。无比沮丧。&lt;/p&gt;
&lt;p&gt;吸取了上次跟腱炎的教训，为了避免情况恶化，这次的我立刻停止了跑步，并去看了理疗师。没有什么严重的问题，但我需要停跑并做强化肌肉力量的练习。有一点失望，但是也没有太意外，毕竟这次马拉松的最后几公里，我的下肢比心肺先到达极限，是我目前的短板。&lt;/p&gt;
&lt;h2 id=&quot;所以现在&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%89%80%E4%BB%A5%E7%8E%B0%E5%9C%A8&quot; aria-label=&quot;所以现在 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;所以，现在？&lt;/h2&gt;
&lt;p&gt;当我意识到马拉松是一项耐力运动，当我一次次在跑道上看到年龄比我大几倍的跑者，如今的我，心态也更加耐心。我知道我还有很大的进步空间，我也相信终有一天我会跑得又快又远，但那一天并不一定要很快发生。如果以十年的时间尺度来思考跑步，一时的伤痛和停跑其实改变不了什么，重要的是一直跑下去。&lt;/p&gt;
&lt;p&gt;如今，我的膝盖已然渐渐康复，也是时候重回跑步，为下一场赛事做准备了……&lt;/p&gt;</content:encoded></item><item><title><![CDATA[二十四岁，充满变化的一年]]></title><description><![CDATA[我生活的方方面面，原来发生了这么多的变化。]]></description><link>https://www.zackwu.com/posts/2023-12-03-a-year-of-change/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2023-12-03-a-year-of-change/</guid><pubDate>Sun, 03 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这是一篇迟到了一周的生日博文，但或许正如标题，拥抱「变化」是我这一年的年度主题。当然，还是要向关注我的现实朋友/网友们说声抱歉。&lt;/p&gt;
&lt;p&gt;如果你在&lt;a href=&quot;/posts/2022-11-26-it-was-random/&quot;&gt;去年&lt;/a&gt;阅读了我的生日博文，或许你当时会觉得那篇文章充满了语焉不详的朦胧，对一些事情有所遮掩。
事实上，也正是如此。在各种意义上，当时其实并不是一个写总结的好时机：许多重要的事情恰处在变化的前夜，抑或悬而未决，抑或不便对外透露。
而在文章中随笔一提的后续文章，最终也一直拖延未写。&lt;/p&gt;
&lt;p&gt;所以，希望今年的文章可以好好地梳理清楚这一年的各种变化，清晰地在人生里程上留下一个印记。&lt;/p&gt;
&lt;p&gt;这一年最大的变化，是去年十月在澳大利亚自驾游的同伴，成为了现在的女朋友。从推特网友，到自驾同行，相遇是随机的偶然；而在去年生日时，是分别后的思念，是透破窗户纸前的忐忑，有太多思绪不能写下。告白之后，依旧是身处异地，她在悉尼，我在新加坡，生活与工作，但有了遥遥的牵挂。得益于国际航班的复苏，又因为我的新工作（在一家金融公司）不支持跨国远程工作，过去这一年里，我在悉尼/新加坡航线上来来回回，对所有航班的时刻与价格几乎已经熟稔。&lt;/p&gt;
&lt;p&gt;好几次，在礼拜五下班后，充满期待地前往机场，坐上夕发朝至的航班，努力地睡上几个小时，然后在第二天清晨，南半球的寒冽中，拥抱睡眼惺忪或者同我一样兴奋难眠的她，忘却飞行的疲惫与出入境的琐碎等待；然后又在周一的午后，不情愿地登上返程的航班，用八小时的飞行与三小时的时差，消化离别，重回没有她在身边的日子。&lt;/p&gt;
&lt;p&gt;几个月前，她来新加坡远程工作，我在凌晨结束一段出差回到新加坡，迫不及待想要与家中的她相聚。打车回家的途中，我让司机在附近的花店稍作停留，带着几支玫瑰上车，不知是因为买花还是异地的辛苦，司机感慨了一句 Lucky her，我一时有些错愕：幸运的人难道不是我吗？于是下意识地回了一句 Lucky me。现在想来，过去一年的奔波与温暖，都是 Lucky us。异地分别不是主动的选择，只是因为爱的人现在恰好不在同一个城市。而在未来的种种可能性中，我能看见，也和她一次次规划，无数种美好，所以彼此愿意等待而心怀幸福。&lt;/p&gt;
&lt;p&gt;宕开一笔。在我的自我介绍页面，我写我的运动爱好「如今仅剩跑步」，倒也没错，但在过去一年，这也发生了不少变化。&lt;/p&gt;
&lt;p&gt;记得在大学的时候，同学们为了素质拓展活动的加分，也出于往届的历史渊源，纷纷参与上海马拉松的志愿者活动。出于某种追求纯粹目的的不合群，当时的我并没有参加，但是当我独自在南体（田径场）一圈圈夜跑的时候，不论是 21 公里还是 42 公里，都感觉无比遥远却心生神往。曾经和好友畅想，当时的我可以一次跑五公里，那么只要每年让自己多跑几公里，也许有朝一日就可以参加上海马拉松，但可惜我在实现之前就已离开上海。&lt;/p&gt;
&lt;p&gt;所以人生中的第一次半程马拉松，留给了去年 12 月的新加坡。在自我怀疑与犹豫中，我最终顺利完成，彷佛征服了一座看不见的高山，在我的跑步轨迹上留下了一双看不见的脚印。在此之后，一发不可收，我兴致勃勃地报名了更多的半程马拉松，并准备在一年后（也就是写下本文的今天，但很明显，我没有参加，而是在写作）挑战完整的马拉松。借着参加半马的名义，在这一年，和她去了不同的地方，度过了许多美好的时光，比如黄金海岸，比如墨尔本，跑步的多巴胺在世界的各个角落混入了我的生活。&lt;/p&gt;
&lt;p&gt;然而乐极生悲，跑步新手最常犯的错误就是操之过急。在我雄心勃勃地觉得自己已经征服半马之后，在我骤然加大训练量准备全马之时，跟腱炎不期而至，让我不得不暂时停下脚步。至此，已然数月。期间在不甘心的试探（比如强行跑了两个半马）和伤痛折磨的无奈中反反复复，最终不得不认清现实：一时的休养是为了以后跑得更远，跑步是未来几十年的事情，相比之下，停跑几个月来学会和自己（的身体）和解，是一节必修的课。长期思维听上去不过是简单的道理，却总需要付出代价后才能明白。不知道在跑步内外，还在哪些方面，还有多少节这样的课等着我。&lt;/p&gt;
&lt;p&gt;或许是工作？是的，过去一年内我换了工作：在写下去年的文章之时，其实已经拿到了现在公司的 offer，并决心从字节跳动离职，只是当时还在各种流程中，所以没有写明。&lt;/p&gt;
&lt;p&gt;对于字节跳动的工作，其实我已经没有什么新的内容可以谈，在去年的文章和曾经的&lt;a href=&quot;/posts/2020-01-18-my-internship-at-bytedance/&quot;&gt;实习感受&lt;/a&gt;中，我想说的大抵已经说完了，这也是我这次离职没有再写一篇类似「我在字节跳动全职的一年半」文章的原因。而且另一方面，我知道字节的同事们都是优秀的人，在工作期间，我已经感受到了不少同事的能力和经验出众，只是公司的环境和文化如此，很多事情没法选择。&lt;/p&gt;
&lt;p&gt;而新的工作，在工作内容上，我的职位依旧是软件工程师，除了改用一门小众编程语言 OCaml，每天的日常依旧是写代码，并不直接涉及金融与交易，只是偶尔需要了解一些专业术语与概念，类比之下，大概类似于互联网行业的「业务」开发。但从公司整体的技术栈来说，和互联网公司追求（或者发明）时新技术的思路不同，我司在很多方面依旧使用着相当「传统」的技术，比如，没有使用 Docker/Kubernetes 之类的云原生方案，而是部署到具体的物理机或虚拟机。但在一开始的惊讶和不适应之后，我也渐渐理解了这些背后的原因。我相信，不论使用何种框架或者工具，作为软件工程师，最核心的技术能力都是相通的。&lt;/p&gt;
&lt;p&gt;但更大的不同，其实不在技术上，而在于工作的环境。我一向自认为英语能力尚可，但第一次在完全英语的环境中工作（微软中国和字节跳动新加坡都只能算是不同程度的半英语环境），最初还是有相当程度的不适应。比起身边无比优秀且英语母语（或者至少有多年英语环境学习/工作经历）的同事，我仿佛失去了语言能力，只能一点点地重新学习如何沟通交流。有时候我甚至分不清，到底是我个性寡言少语，还是因为不懂得如何用英语自如表达，才显得比其他人沉默。过程是艰难的，但也是必经之路，好在同事们都相当包容理解。&lt;/p&gt;
&lt;p&gt;除去语言因素，公司整体的文化氛围依旧和字节跳动相去甚远：更严格的工作生活分离，更注重代码质量和 code review，更多的代码之外的人际沟通，更充分的入职培训与辅导，更频繁地和上司的一对一聊天，更多的邮件往来……如此种种，不一而足。但谈论工作不是本文的主要意图，所以就不一一展开了，如果有必要的话，或许之后会写一篇文章来专门探讨这份工作。&lt;/p&gt;
&lt;p&gt;整体来说，我对现在这份工作相当满意，能够在工作中不断有所获得，同时也有足够的空间留给生活。考虑到工作在我生活中所占的比重，这次跳槽带来的积极变化，可谓是相当幸运。&lt;/p&gt;
&lt;p&gt;最后的最后，一些似乎重要又似乎没有那么重要的变化。在这一年，我拿到了新加坡的 PR 身份：曾经对此心心念念，但拿到后我的生活似乎又没有太大的变化，工作与生活照旧，只是多了一点点安全感，不必担心失业后被逐出我生活了两年多的家。我一直觉得所谓归属感是一种很虚无缥缈的东西，可这一年不论是因为出差还是因为旅行，去了很多地方，当飞机落地樟宜机场时，它的亲切与熟悉，它的高效与可信赖，让我无比心安。&lt;/p&gt;
&lt;p&gt;所以，就这样飞来飞去，就这样停下脚步思考，就这样在新的环境中，写下过去一年的变化，迎接新一年的变化。顺便给自己一个，迟到的生日快乐。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[二十三岁，当时只道是偶然]]></title><description><![CDATA[似乎是平平无奇的一年，又似乎偶然地发生了很多事情。随机漫步，大概如此。]]></description><link>https://www.zackwu.com/posts/2022-11-26-it-was-random/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2022-11-26-it-was-random/</guid><pubDate>Sat, 26 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在人生的坐标轴上，倘若我需要为过去一年找到某些独特的标签，那么，唯一可以贴上的，大概只有：这是我第一个全职工作的完整年份。去年今日尚存一些对校园生活的怀念与对照，以及身份切换与来到异国的种种新鲜感，但时至今日，这些似乎已经快要消失殆尽了。&lt;/p&gt;
&lt;p&gt;所以，回顾这一年，我的第一感受是平平无奇，按部就班地工作与生活，没有太多的波澜。至少，没有我可以现在公开写下来的波澜，或许不久之后，我会再写一篇文章。&lt;/p&gt;
&lt;p&gt;但转念一想，此时此刻，我所面对的工作与人生，选择与纠结，似乎早已在过去一年（甚至更久之前）的各种不经意间偶然地注定，只是随机地延宕至今。&lt;/p&gt;
&lt;p&gt;那么，就用平淡与偶然来标记这一年吧。&lt;/p&gt;
&lt;h2 id=&quot;平淡&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%B9%B3%E6%B7%A1&quot; aria-label=&quot;平淡 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;平淡&lt;/h2&gt;
&lt;p&gt;在过去的一年，我的博客没有更新任何文章，第一次让两篇生日文章无缝衔接，其实已然说明了一切的平淡。当然，也有我表达欲的淡退，这就是另一个话题了。&lt;/p&gt;
&lt;p&gt;翻看去年的文章，其实当时的我已经隐隐感受到了所谓「&lt;a href=&quot;/posts/2021-11-26-bigger-world-and-inner-peace/#%E5%B7%A5%E4%BD%9C&quot;&gt;工作的平凡（triviality）&lt;/a&gt;」。但坦诚而言，理性上的认知与实际的长期（其实我知道一年也不算长，毕竟将来的职业生涯还有几十年）感受是两回事，而这一年的平淡更多指的是后者。&lt;/p&gt;
&lt;p&gt;去年写下生日文章的时候，我加入字节尚且不到半年，大概处于一种新鲜劲头与繁琐日常的交叠期间。而在之后的这一年，这样的平淡感整体与日俱增，尤其是在我渐渐熟悉了解项目、提升能力之后，愈发觉得所做的项目乏味与质量低下，试图推进的一些改变也因为其他人看不到明显的收益和我个人能力不足以独支而无疾而终，因而陷入了更深的倦怠，对工作的兴致转移到生活中的各种其他事情，比如烹饪与运动。&lt;/p&gt;
&lt;p&gt;今年四月，绩效结果出来之后，在主动选择和领导建议下，我内部转组到了一个更加有意思、也更加有技术含量的方向，重新点燃了对工作的热情（毕竟工作内容更加满足我入职前的想象了）。在接下来的几个月时间内，几乎从零开始学习到了许多，同时也稍微做出了一点事情。&lt;/p&gt;
&lt;p&gt;然而变化总是无常。在不久前的半年绩效评估结束之后，又因为新加坡与中国的组织架构变动，我被动地转到了另一个更新但是也很有意思的方向。随遇而安，毕竟只是工作而已，再次以新人的身份在组内学习，重新上手。&lt;/p&gt;
&lt;p&gt;工作上的事情总是如此，乏善可陈，也不便提及太多细节。&lt;/p&gt;
&lt;p&gt;而在热带生活，我也渐渐失去了对时间流逝的真切感知，每天彷佛都一模一样。T 恤们排着队，在我身上、脏衣筐、洗衣机和衣柜里来来回回，我甚至有点对它们感到同情。不过，我的感受又不同于很多人对新加坡的感受：很多人不喜欢新加坡，因为它太小，很容易让人厌倦。但对我而言，生活的重复与平淡，责任不在于新加坡，或者说，与环境无关，而更多在我本身：哪怕是新加坡这样的小岛，我居于此一年多，去过的地方甚至不如游客们一日内打卡的景点多。而且，在绝大多数的时间，重复与平淡是我的主动选择，反而意味着舒适与自在，并不是一种抱怨。生活而已，唯一的缺点就是没什么可写的。&lt;/p&gt;
&lt;h2 id=&quot;偶然&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%81%B6%E7%84%B6&quot; aria-label=&quot;偶然 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;偶然&lt;/h2&gt;
&lt;p&gt;回看很多事情的发生，其实不过是偶然。但偶然的魅力不在于偶然，而在于一丝一缕的关联与注定。&lt;/p&gt;
&lt;p&gt;来新加坡与字节跳动，则是一切偶然的开端。2020 年，字节跳动刚刚开始在新加坡扩建海外分部，而之前与我共同在微软实习的朋友恰巧在字节跳动实习，且他所在的组正在组建对应的新加坡团队，因而机缘巧合，我拿到了面试机会与 offer，成为了首批为数不多的直接从国内校招来到新加坡的幸运儿。后续的国内直招，据传因为 EP（Employment Pass）的配额原因而并不顺利，所以我偶然间搭上的，算是某种意义的首班车与末班车。&lt;/p&gt;
&lt;p&gt;虽然不愿意去谈，但是回想这一年大陆的各种防疫消息与事件，以及近期各种骇人听闻的新闻，我似乎又觉得自己偶然间成为了幸运儿：我在国内期间享受了那段可以自由境内旅行的防疫红利期，毕业前和室友们一起快乐地旅行，一次核酸检测都没有做过（我人生唯一一次核酸检测是在樟宜机场落地）。但这都不过是偶然而已，和我的能力或选择并没有什么关系，而目前尚在大陆的朋友们也什么也没有做错。可是，这种偶然又是为什么呢？谁造就了这种偶然呢？&lt;/p&gt;
&lt;p&gt;上文说到我对工作的倦怠，应对倦怠的方法之一是转移注意力到生活。今年十月份，我休了一个长假，三个礼拜有余，只身飞往澳大利亚，和朋友一起自驾游。偶然认识的朋友，偶然定下的行程，偶然决定的自驾，偶然看到的彩虹与各种沿途风景，以及偶然的收获。在行程结束后的几个礼拜，我产生了一种深深的自我怀疑与对未来的怀疑：如果一切都是偶然，那么对未来的各种美好规划其实只不过是一个人的过家家，命运并不会参与。但现在的我更愿意这么想：既然无可避免，人生的魅力便在于事的偶然与人的缘分，随时准备面对下一刻的未知。&lt;/p&gt;
&lt;p&gt;另一个方法则是，用更多的空余时间提升自我。在百无聊赖的航班上，仔细阅读逃生手册不失为一种消遣。从我对工作不再兴致高昂的那一天起，落入俗套地，我开始学习准备有朝一日的降落伞，Leetcode 刷题也好，提升英语能力也好，LinkedIn 探索也罢……虽然现在还没有到需要跳伞的那一天，但如今回首，我似乎也做完了很多事情：Leetcode 周赛全球前 100，不再担心任何公司的技术面试；雅思 8.5 分，不论是为了将来移民还是面试，都至少有了信心；以及各种日积月累学到的技能与知识。偶然而已，不过或许某一天这些偶然可以拼凑成完整的注定。&lt;/p&gt;
&lt;h2 id=&quot;总结&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%80%BB%E7%BB%93&quot; aria-label=&quot;总结 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;总结&lt;/h2&gt;
&lt;p&gt;这篇文章的时间点比较特殊，平淡与偶然尚且交织，很多事情尚无定论。但也无可奈何，我的生日就是今天。所以如果你读下来觉得不明所以，你的感受是对的，很抱歉。&lt;/p&gt;
&lt;p&gt;总而言之，在完整地过完这一年之后，我对工作的看法和去年大体一致，只是多了一些切身的体会。而对于生活，或者人生，我则越来越失去了掌控感，越来越感受到随机与偶然的魅力。但现在最棒的事情是：不论是工作还是人生，我都还有几十年的光阴慢慢去探索，所以，顺其自然地随机漫步吧。&lt;/p&gt;
&lt;p&gt;在热带的第二年，祝我生日快乐。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[二十二岁，追寻更大的世界与更平和的内心]]></title><description><![CDATA[这一年，向外探索了新的生活与工作，也在努力向内追求更加从容的心境，以种一棵树的心态在森林漫步。]]></description><link>https://www.zackwu.com/posts/2021-11-26-bigger-world-and-inner-peace/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2021-11-26-bigger-world-and-inner-peace/</guid><pubDate>Fri, 26 Nov 2021 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;种一棵树最好的时间是明天。—— 我自己&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;又是一年的光阴。但与往年不同的是，这是我这辈子第一个穿着 T 恤度过的生日，伴着窗外阵阵夏夜晚风。（所以，本文的 BGM 可以是 &lt;a href=&quot;https://y.qq.com/n/ryqq/songDetail/4932428&quot;&gt;夏夜晚风 - 伍佰 &amp;#x26; China Blue&lt;/a&gt;。）&lt;/p&gt;
&lt;p&gt;这一年，或许是近些年来我的生活发生最大变化的一年：从听课写作业的学生，毕业成了开会写代码的程序员；从上海闵行郊区的宿舍群居，搬到了新加坡市区的出租屋。新的生活，新的工作，其间发生的许多事情对于一年前的我完全属于意料之外。&lt;a href=&quot;/posts/2020-11-26-choices-and-my-future/&quot;&gt;当初辗转反侧做出的选择&lt;/a&gt;，这一年来，其实也已经或多或少地被推翻了一些。&lt;/p&gt;
&lt;p&gt;去年生日前后，决定毕业后去阿里云而忍痛拒绝了微软和 Shopee 的校招 offer。但谁能料到在春节前后，意外地从在字节跳动实习的朋友处得知字节跳动正在扩张新加坡团队，几轮面试之后，最终又决心毁掉了和阿里云的三方协议。其后，毕业前的几个月，一面是在学校做着毕业设计，一面则是准备着各种毕业后赴新加坡的事务。疫情期间，虽然说服了父母，但不论是办理护照还是签证，都感觉彷佛是在和整个世界逆行。&lt;/p&gt;
&lt;p&gt;七月，一张机票，从上海的酷暑飞向了热带的永恒夏日，开始了截然不同的生活，也开启了我的第一份正式工作。&lt;/p&gt;
&lt;p&gt;而现在，回顾我这充满变化的一年，又有什么感触呢？就从工作和生活两方面，谈谈我的一些心路历程吧。&lt;/p&gt;
&lt;h2 id=&quot;工作&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%B7%A5%E4%BD%9C&quot; aria-label=&quot;工作 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;工作&lt;/h2&gt;
&lt;p&gt;熟悉我的朋友们或许知道，在大学期间，我曾在字节跳动有过一段 &lt;a href=&quot;/posts/2020-01-18-my-internship-at-bytedance/&quot;&gt;不甚愉快的实习经历&lt;/a&gt;，但也算是机缘巧合，我重新踏入了同一条河流。当然，也不完全是同一条，至少，是在不同国家的流域。&lt;/p&gt;
&lt;p&gt;在字节跳动新加坡的工作，作为我的第一份正式工作，一如当初在字节跳动我的第一次实习工作，都给我带来了一些认知上的变化。&lt;/p&gt;
&lt;p&gt;工作本身，基础架构，按照我入职之前的幻想（脑海里堆叠诸如分布式、存储系统、NoSQL 等等听上去「高大上」的技术名词），带有不少神秘的高技术含量色彩。但在入职后，渐渐熟悉了组内的项目和工作内容，随之也不断地实现了祛魅：所谓的基础架构，其实也不过是写代码，所追求的目标或许在某些时候倾向于极致，但多数时候，对于多数的团队成员，需要做的事情其实和其他领域的项目也没有太大区别。所以，对于我来说，这几个月的工作，开会讨论、写设计文档、编码、写测试、Code Review、线上运维等等，应该也算是比较常规的职业开端了，不好不坏。&lt;/p&gt;
&lt;p&gt;但需要说明的是，认清工作的平凡（triviality）对我来说并不主要是一种失望，更多地，反倒让我能够有更加平和的心态来面对工作。譬如，我现在很清晰地认为，工作的本质无非是替公司解决问题而获得报酬，因而会有很明确的界限感，追求 Work Life Balance，而非许多（尤其是国内的）字节员工将工作与生活完全揉杂的态度（工作日加班、周末和领导同事一起出来玩）。试图在工作中（过度地）追求个人成长和技术成长，或许很大程度上是一种「本末倒置」，将工作的副作用当做了目的。因此，当团队领导对我说「你要对自己的成长负责」这句话的时候，我相信我对这句话的理解和他的企图完全是相反的：如果要对自己的成长负责，就不应该完全投入到工作中去。&lt;/p&gt;
&lt;p&gt;那么，从这些角度来看，其实我对这份工作目前的状态相当满意：从来不加班，每天我有充足的时间属于自己，不论是打游戏、刷剧杀时间，还是看书、写自己的代码。&lt;/p&gt;
&lt;p&gt;这样就很好。&lt;/p&gt;
&lt;h2 id=&quot;生活&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%94%9F%E6%B4%BB&quot; aria-label=&quot;生活 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;生活&lt;/h2&gt;
&lt;p&gt;作为典型的小镇青年，在拿到新加坡工作 offer 之后，我才有了自己的护照，第一次来到异国他乡。但与此同时，我又是一个相对宅家而习惯独处的人。所以，生活上的变化，不大也不小。&lt;/p&gt;
&lt;p&gt;来到新加坡，有两件意外且有趣的事情：一是当地人的英语和中文一开始都我来说都很费解，不过熟悉之后，倒也算是能领悟新加坡的特色语法和用词了；二是这里虽属热带，没有四季之分，但由于降雨很频繁，所以整体气候其实不算炎热，体感上比上海的夏天要凉快。&lt;/p&gt;
&lt;p&gt;而在其他方面，除了初来之时的陌生感与各种琐碎事务处理，时至今日，我的生活已然完全找到了相对舒适且稳定的轨迹：工作日，八点起床，九点到下午五点多在家工作（因为疫情，我已经好几个月没有去过办公室了），之后则是和朋友的聊天交流，以及属于自己的娱乐、运动、学习时间；周六上午，早早起床，规划好周末两天的食谱，然后去附近的超市买食材（逛超市并拎着一堆东西回家，有一种简单而充盈的满足感，伴着「不够发达」的物流，这让我几乎戒掉了网购的习惯），在做午饭和晚饭的时间之外，做家务，打扫卫生，当然还有娱乐和阅读。另外，作为一个除了睡觉就在上网冲浪的人，我很喜欢新加坡的网速和无界的互联网，这给我省去了很多不必要的烦恼。&lt;/p&gt;
&lt;p&gt;唯一的不足，或许是偶尔会觉得有一点孤独难以排解，只能独对自我。不过，也只是偶尔罢了。&lt;/p&gt;
&lt;p&gt;另外，说回到上一部分提到的「个人成长」。如本文一开头的我自己的那句引言所述，「种一棵树最好的时间是明天」，不像很多同龄人，我并不焦虑于成长的速度。平均而言，我每天投入到学习的时间应该不过一个小时，甚至没法读完技术书籍的一个章节。但在这一年的各种纠结与挣扎之后，不论是关于人生选择还是竞争，我渐渐学会了放平心态，用自己觉得舒服的方式和节奏，慢慢来会比较开心。&lt;/p&gt;
&lt;h2 id=&quot;总结&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%80%BB%E7%BB%93&quot; aria-label=&quot;总结 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;总结&lt;/h2&gt;
&lt;p&gt;所以，如何总结我这一年呢？我没有确切的答案，即便有，我相信再过几年，当我回头来看这段时光，大概率会推翻我所作出的任何总结。&lt;/p&gt;
&lt;p&gt;但不论如何，工作与生活，变化与选择，不断地向外探寻更多的可能性，同时向内追求心灵的平静与从容，是我已经做了，正在做，也将继续做下去的事情。&lt;/p&gt;
&lt;p&gt;二十二岁，学会和世界、和自己相处，生日快乐。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[更换域名，以及一些其他变化]]></title><description><![CDATA[从 imwzk.com 更换为 zackwu.com，对网站备案制度说不，拥抱更加开放易用的互联网]]></description><link>https://www.zackwu.com/posts/2021-11-13-change-of-domain-and-other-things/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2021-11-13-change-of-domain-and-other-things/</guid><pubDate>Sat, 13 Nov 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;简而言之，在过去的一天内，本站完成了以下几件部署上的变化：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;域名从 &lt;code class=&quot;language-text&quot;&gt;www.imwzk.com&lt;/code&gt; 更换为 &lt;code class=&quot;language-text&quot;&gt;www.zackwu.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;上一条的潜在影响是，新域名没有（将来也不打算）在国内进行 ICP 备案，所以网站无法继续部署在国内云服务上&lt;/li&gt;
&lt;li&gt;因此，本站的部署由 Github Action + 腾讯云（国内）+ AWS（海外），切换为统一的 Netlify + Cloudflare CDN&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上述变化，从网站访客的视角来看，大致会有以下影响：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对 &lt;code class=&quot;language-text&quot;&gt;www.imwzk.com&lt;/code&gt; 和 &lt;code class=&quot;language-text&quot;&gt;imwzk.com&lt;/code&gt; 的访问请求会被 &lt;code class=&quot;language-text&quot;&gt;301 Moved Permanently&lt;/code&gt; 重定向到新的域名（希望原来的朋友们不会迷路）&lt;/li&gt;
&lt;li&gt;国内的朋友们，访问本站可能会出现 &lt;strong&gt;十分明显&lt;/strong&gt; 的速度下降，部分地区甚至可能无法访问&lt;/li&gt;
&lt;li&gt;海外的朋友们，访问本站应该没有任何体验差异，如果有，应该是些微地更加顺畅丝滑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而对我自己而言，这几天的感受变化有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;部署变得更加简单方便
&lt;ul&gt;
&lt;li&gt;原本是手动写 Github Action 流程来做构建，并主动上传至腾讯云对象存储，刷新腾讯云 CDN。这一套流程有一点繁琐，但好在可以自动化，平日也不算负担；但由于国内的特殊网络状况，在特殊时期，Github Action 与腾讯云的交互偶尔会出现网络问题，导致部署失败，不得不多次重试，有一些恼人。&lt;/li&gt;
&lt;li&gt;现在使用 Netlify 自动构建，几乎不需要任何配置，且顺带获得了相对完善的 CI/CD 体验。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;云服务更加简单易用
&lt;ul&gt;
&lt;li&gt;对于轻度的云服务个人用户（与之相对的，是各大云服务商追逐的企业用户、大客户），国内的几家云服务商，腾讯云其实已然算是相对用户友好的一家。但强制使用微信扫码登录，敏感操作强制扫码验证，以及交互方式略微僵硬的管理后台，相信其他使用者和我应该有同感。&lt;/li&gt;
&lt;li&gt;现在使用 Netlify 和 Cloudflare，整体的感受是，不论是 UI 还是交互，都更加用户友好，普通用户应该可以更加符合直觉地轻松上手，而专业用户也能拥有更多更强大的高级特性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;离更加自由的互联网更进一步
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;www.imwzk.com&lt;/code&gt; 这个域名当初于腾讯云注册，并完成了 ICP 备案（唯一目的是使用国内的 CDN，优化国内的朋友们的访问体验）。&lt;/li&gt;
&lt;li&gt;备案自然非我所愿，按照我对互联网的理想，我痛恨一切审查与备案；但真正的问题是，为了一些正当的目的（如更快的访问速度），付出一点没有实际损失的代价（仅仅是在线提交了一些材料），这是否算是可以接受？曾经的我的答案倾向于肯定，但现在的我渐渐认识到，默许即是纵容，不说 Yes 也不说 No，希冀持着保留意见而获得好处，这种沉默在庞大的制度面前其实相当于 Yes。每一个沉默的 Yes 都意味着制度的瓦解可以沉默地往后推迟几秒。&lt;/li&gt;
&lt;li&gt;另外，按照个人网站备案的规定，理论上任何形式的用户交互内容均是不被允许的（比如，文章下面的评论区）。虽然我至今没有因此收到任何通知，但这始终是一条可以被选择性执法的软肋。我讨厌这种有把柄在别人手上的感觉。当然，这个把柄本身，按照我的认知，其实根本就不应该存在。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后，如果你依旧认同我的理念，依旧愿意继续阅读我对生活的记录与思考，别忘了更新一下你的 RSS 阅读器中本站的订阅链接，你的浏览器书签，又或者是对本站的友情链接。&lt;/p&gt;
&lt;p&gt;抱歉带来这样的小小麻烦。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We shall meet in the place where there is no darkness. — 1984&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[初来新加坡，一份简单的个人金融事务指南]]></title><description><![CDATA[作为初来乍到的外国人，如何优雅从容地适应新加坡生活，处理好个人金融的方方面面？本文将尽量全面而简洁，介绍我这几个月的经历与心得。]]></description><link>https://www.zackwu.com/posts/2021-09-22-personal-finance-in-singapore-for-expats/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2021-09-22-personal-finance-in-singapore-for-expats/</guid><pubDate>Wed, 22 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;写在前面&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%86%99%E5%9C%A8%E5%89%8D%E9%9D%A2&quot; aria-label=&quot;写在前面 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;写在前面&lt;/h2&gt;
&lt;p&gt;本文是一份&lt;strong&gt;简单的、不全面的、不一定靠谱的、仅仅依靠我的个人经历产生&lt;/strong&gt;的个人金融（Personal Finance）事务指南，将会从我的视角介绍新加坡日常个人金融的基本情况，并给出一些仅供参考的建议（当然，绝对更不构成投资理财建议，这里就不赘述免责声明了）。&lt;/p&gt;
&lt;p&gt;大体而言，本文会涉及普通外国人在新加坡日常生活会遇到的主要个人金融场景，比如 SingPass（其实这并不属于金融），银行账户，信用卡，数字支付，保险以及投资理财。而出于篇幅和其他原因，本文&lt;strong&gt;不会&lt;/strong&gt;包括租房，水电网络，日常消费，网购外卖，看病医疗，新加坡工作体验等话题，虽然这些活动某种程度上也和钱息息相关，也需要一定的探索和适应。不过，将来我或许也会单独开文谈谈这些话题。&lt;/p&gt;
&lt;p&gt;在开始前，先简单介绍一下自己：国内大学本科应届毕业生，两个多月前直接通过校招来到了新加坡的字节跳动，因而从零开始探索了新加坡的个人金融的各个方面，其间因为没有足够的知识与能力，加之不甚了解新加坡个人金融体系与国内（特指中国大陆，下同）的差异，踩了一些坑，所幸整体还算顺利。因此，写这篇文章，分享我这几个月的经历与心得，希望可以帮助到有需要的朋友，以及两个月前的我，如果有时光机的话。&lt;/p&gt;
&lt;p&gt;顺便说明，&lt;strong&gt;本文不会带有任何推广链接&lt;/strong&gt;，所以可以放心阅读。&lt;/p&gt;
&lt;h2 id=&quot;singpass&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#singpass&quot; aria-label=&quot;singpass permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SingPass&lt;/h2&gt;
&lt;p&gt;有趣的是，虽然本文的主题是个人金融，但率先讨论的 &lt;a href=&quot;https://www.singpass.gov.sg/main/&quot;&gt;SingPass&lt;/a&gt; 其实&lt;strong&gt;并不是金融产品&lt;/strong&gt;，而是新加坡政府运营的数字化身份证明。援引一段其网站上的介绍：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Singapore Personal Access (or Singpass) is Singapore citizens’ and residents’ trusted digital identity for convenient and secure access to thousands of government and private sector services, online and in person.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;其对于个人金融的重要性在于，当有了 SingPass 之后，在申请诸如银行账户、信用卡等金融产品时，可以直接从 SingPass &lt;strong&gt;一键获取并验证&lt;/strong&gt;个人信息。客观来说，虽然新加坡的数字支付不如国内发达，但在这个方面，比起国内的许多产品动不动就要求上传身份证（甚至要求手持）进行实名制，新加坡能有这样官方的数字化身份信息平台，还是很值得称赞好评的。&lt;/p&gt;
&lt;p&gt;而使用 SingPass 申请的好处是，不仅省去了很多手动填写表单的麻烦（比起国内银行开户，新加坡银行会要求提供格外多的信息），也能够&lt;strong&gt;更快更容易地通过申请&lt;/strong&gt;。后者基于我和室友的超小样本对照试验：我俩有着基本上完全一致的背景信息，但是在申请信用卡时，他由于一开始没有使用 SingPass，等了将近一个多月也没审批通过；而我的几张信用卡均在一个礼拜内申请通过。&lt;/p&gt;
&lt;p&gt;因此，在入境新加坡并获得了合法的签证身份之后，即便尚且没有收到实体的签证卡，我的建议是提前在 SingPass 官网完成注册和身份验证（可能会邮寄一次性验证码到登记的居住地址，这需要等好几天），以便尽早获得 SingPass，避免影响后续的其他事项。而如果不想等待数天的验证码邮寄，抑或是在网上注册流程遇到问题，可以直接带上身份证件，选择就近的社区网点现场办理，可以&lt;strong&gt;当场完成&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;银行账户&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%93%B6%E8%A1%8C%E8%B4%A6%E6%88%B7&quot; aria-label=&quot;银行账户 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;银行账户&lt;/h2&gt;
&lt;p&gt;对于绝大数人（或者不谨慎一些，所有人），拥有新加坡的本地银行账户（Saving Account）以及相配套的借记卡（Debit Card）是开启个人金融生活的第一步：为了准时收到公司发的工资，为了给房东交租，为了给国内的亲友汇款，不一而足。&lt;/p&gt;
&lt;h3 id=&quot;开户&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%BC%80%E6%88%B7&quot; aria-label=&quot;开户 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;开户&lt;/h3&gt;
&lt;p&gt;理论上来说，不同于申请信用卡，开立银行账户（即国内银行的储蓄卡）是一件没有任何门槛的事情：不需要工作证明，也没有收入门槛。但需要注意的是，新加坡的金融体系格外看重&lt;strong&gt;居住地址证明（Proof of Residential Address）&lt;/strong&gt;，在提供有效的身份证明之外，所有银行的开户和信用卡申请都一定会要求提供有效的居住地址证明，很多人（比如之前的我）往往会在此遇到困难。而什么是有效的居住地址证明呢？以 &lt;a href=&quot;https://www.dbs.com.sg/personal/support/bank-account-opening-documents-required.html&quot;&gt;DBS 银行的开户文件要求&lt;/a&gt; 为例，其他银行也大体类似：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Proof of Residential Address&lt;/p&gt;
&lt;p&gt;Provide the latest copy (within last 3 months) of any of the items below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In Principal Approval (IPA) issued by Ministry of Manpower&lt;/li&gt;
&lt;li&gt;Work permit of foreign domestic worker (domestic helper) issued by Ministry of Manpower before 24 August 2020&lt;/li&gt;
&lt;li&gt;SGWorkPass App screenshot for foreign domestic worker (domestic helper) issued by Ministry of Manpower after 24 August 2020&lt;/li&gt;
&lt;li&gt;Letter of offer&lt;/li&gt;
&lt;li&gt;Letter of employment&lt;/li&gt;
&lt;li&gt;Latest payslip&lt;/li&gt;
&lt;li&gt;Local utility bill&lt;/li&gt;
&lt;li&gt;Local telecommunication bill&lt;/li&gt;
&lt;li&gt;Local bank statement/credit card statement&lt;/li&gt;
&lt;li&gt;Letter issued by government of other public bodies regulated for AML practices in a FATF member country&lt;/li&gt;
&lt;li&gt;2Letter from regulated insurance companies in a FATF member country&lt;/li&gt;
&lt;li&gt;Acceptance letter from school (restricted to official letters from educational institutions or schools under the purview of Council for Private Education or Ministry of Education)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;简单来说，即是&lt;strong&gt;明确带有姓名和住址的上述文件之一&lt;/strong&gt;。其中，最为常用的一般是水电网络账单、其他银行结单（Statement）。而对于初来新加坡的外国人而言，最大的问题在于：即便已经租好了房子，首月也并不会收到水电网络账单；offer 文件和雇佣合同之类的文件上，一般并没有住址，即便有，也大概率是来新加坡之前的国内地址；更不用说递归调用的其他银行结单。&lt;/p&gt;
&lt;p&gt;基于此，一部分公司会为员工出具证明，比如 Shopee，从而使其可以在合作的银行（UOB 银行）十分简单顺利地开立账户。而如果公司不提供这类证明，比如字节新加坡，那就得靠自己开动脑筋灵活发挥了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;理论上而言，单纯的租房合同（房客和房东之间）不被视作有效的居住地址证明（我个人猜测原因可能是难以验证其真实性），并不包括在上面引用的文件列表之内。但部分银行的部分网点，实际上会接受租房合同，这就需要&lt;strong&gt;多走访几家网点尝试&lt;/strong&gt;了。我室友即是在 OCBC 银行通过租房合同成功开户。&lt;/li&gt;
&lt;li&gt;租房合同本身难以验证，但如果换一个思路，作为租客，在租房时需要承担印花税，会得到一张政府机构出具的印花税单（Certifacte of Stamp Duty），上面包含了租客的姓名和房产地址，这毫无疑问是可验证的。因此，尽管 DBS 的上述列表中没有提到，但根据我的亲身实践，&lt;strong&gt;印花税单是有效的居住地址证明文件&lt;/strong&gt;，可以用以开户。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;选哪家银行的账户&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%80%89%E5%93%AA%E5%AE%B6%E9%93%B6%E8%A1%8C%E7%9A%84%E8%B4%A6%E6%88%B7&quot; aria-label=&quot;选哪家银行的账户 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;选哪家银行的账户？&lt;/h3&gt;
&lt;p&gt;在来到新加坡的首月，由于尚未具备充足的证明文件，为了尽快拥有银行账户和借记卡，其实往往没得选：要么选择公司合作的银行，要么选择能够接受你的地址证明的银行。&lt;/p&gt;
&lt;p&gt;而在此之外，如果有选择余地，新加坡的金融体系相当发达，在银行方面，实现了「中西交融」，大致有以下类别的银行可选：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新加坡本土银行，如 DBS、UOB、OCBC&lt;/li&gt;
&lt;li&gt;西方外资银行，如 HSBC、Citibank&lt;/li&gt;
&lt;li&gt;中资银行，如中国银行&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;较为完整的列表和对比可以参见 &lt;a href=&quot;https://www.singsaver.com.sg/bank-account/savings-accounts&quot;&gt;SingSaver&lt;/a&gt; 或者 &lt;a href=&quot;https://www.moneysmart.sg/savings-account&quot;&gt;MoneySmart&lt;/a&gt; 网站上的信息。（顺便一提，这两个网站的信息极其丰富有用，尤其是关于信用卡。）&lt;/p&gt;
&lt;p&gt;然而，对于一般人，即&lt;strong&gt;没有一大笔资产要存进银行账户的人&lt;/strong&gt;，这些银行账户其实几乎没有太大区别：&lt;strong&gt;他们的基础年化利率都一样地低&lt;/strong&gt;，即便精心钻研其复杂的利率公式（比如通过投资、购买保险等行为获取 bonus 利率），也不过是获得 &lt;strong&gt;1% 左右的年化利率&lt;/strong&gt;，我个人认为&lt;strong&gt;从时间精力成本上来看是不必要的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;因此，如果要选择一家银行的银行账户，我的建议是不必考虑其提供的年化利率，而更多关注以下方面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;手机 APP 和网银的易用性（这一点强烈推荐 DBS，我个人感觉其使用体验胜过国内所有的个人银行，&lt;a href=&quot;https://www.euromoney.com/article/28ndltyvx1yx64j262gw1/awards/awards-for-excellence/asias-best-digital-bank-2021-dbs&quot;&gt;甚至有排名为证（仅供参考）&lt;/a&gt;）&lt;/li&gt;
&lt;li&gt;网点及 ATM 的分布（毕竟新加坡目前还是现金支付社会，ATM 取现是一件不可避免的事情，而跨行取现会产生手续费，这一点推荐 OCBC、UOB、DBS 等本土银行）&lt;/li&gt;
&lt;li&gt;转账回国的方便程度（没有使用过其他银行的服务，但 DBS 汇款回国内银行账户相当便利，工作日可以做到几乎秒到，而且汇率相当优惠；不过这一点并不太重要，因为市面上有许多第三方的跨境汇款工具）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可能你注意到了上述描述对 DBS 的偏爱，其实原因也很简单：我目前使用的就是 DBS 银行账户，虽然没有使用过其他银行的银行账户，但其体验已然相当令我满意。而且在我的个人金融体系中，银行账户是不甚重要的一环，所以没有过多的研究对比。另外，一个额外的小例证是：我室友一开始使用 OCBC 的银行账户，但向我多次吐槽后，最终也转向了 DBS。&lt;/p&gt;
&lt;h2 id=&quot;信用卡&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BF%A1%E7%94%A8%E5%8D%A1&quot; aria-label=&quot;信用卡 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;信用卡&lt;/h2&gt;
&lt;h3 id=&quot;真的需要信用卡吗&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%9C%9F%E7%9A%84%E9%9C%80%E8%A6%81%E4%BF%A1%E7%94%A8%E5%8D%A1%E5%90%97&quot; aria-label=&quot;真的需要信用卡吗 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;真的需要信用卡吗？&lt;/h3&gt;
&lt;p&gt;有些人可能会视信用卡为超前消费的坏习惯，在此我也不打算论述信用卡对于个人金融的必要性。事实上，在绝大多数的日常生活场景中，信用卡确实不是必需品，完全可以用现金支付和借记卡替代。&lt;/p&gt;
&lt;p&gt;不过，考虑到新加坡金融体系依旧是&lt;strong&gt;较为典型传统的西方金融体系，很多场景下信用卡是主流甚至默认的支付选择&lt;/strong&gt;，我建议最好还是拥有一张个人信用卡。另外，超前消费本身并不一定是贬义词；相反，如果从个人现金流的角度来看，信用卡可以在消费行为和实际支出之间制造&lt;strong&gt;时间差&lt;/strong&gt;，只要按时还款，相当于始终从银行获取了&lt;strong&gt;无息贷款&lt;/strong&gt;，顺便还能享有各种&lt;strong&gt;信用卡权益&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;因此，只要你不是信用卡有额度就会控制不住自己的消费，在新加坡，拥有信用卡绝对是一件必要且收益颇丰的事情。&lt;/p&gt;
&lt;h3 id=&quot;从哪里了解信用卡信息&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BB%8E%E5%93%AA%E9%87%8C%E4%BA%86%E8%A7%A3%E4%BF%A1%E7%94%A8%E5%8D%A1%E4%BF%A1%E6%81%AF&quot; aria-label=&quot;从哪里了解信用卡信息 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;从哪里了解信用卡信息？&lt;/h3&gt;
&lt;p&gt;如前所述，新加坡作为东南亚的金融中心，信用卡的选择相当丰富，其信息可以从以下几个网站获取：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moneysmart.sg/credit-cards&quot;&gt;MoneySmart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.singsaver.com.sg/credit-card/best-deals&quot;&gt;SingSaver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://seedly.sg/reviews/credit-cards&quot;&gt;Seedly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这三个网站的信息丰富程度上大同小异），不过偶尔会有&lt;strong&gt;不同的新用户促销活动&lt;/strong&gt;，可以对比使用。且除了简单的列表对比，这些网站对一些话题还有较为详尽的博客文章分析（不限于信用卡），有空可以多浏览，熟悉了解新加坡的金融体系。&lt;/p&gt;
&lt;p&gt;另外，如果想要详细了解某张具体信用卡的规则（Terms &amp;#x26; Conditions），可以前往其银行的官网查看，一般都会有单独的页面，以及多个冗长的英文 T&amp;#x26;C 文档供研究。否则的话，很有可能会出现你兴冲冲地用某张卡花了一大笔钱，期待获得丰厚的返现，却最终发现这一消费早已被 T&amp;#x26;C 排除在外。&lt;/p&gt;
&lt;p&gt;总体上来说，与国内相比，新加坡的信用卡&lt;strong&gt;种类更加丰富&lt;/strong&gt;（你能想象国内的一个城市就有上百种信用卡发行吗？），&lt;strong&gt;权益（不论是返现还是积分里程）都更加简单直接且丰厚&lt;/strong&gt;，&lt;strong&gt;新用户礼&lt;/strong&gt;也相当诱人。&lt;/p&gt;
&lt;h3 id=&quot;所以选什么信用卡&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%89%80%E4%BB%A5%E9%80%89%E4%BB%80%E4%B9%88%E4%BF%A1%E7%94%A8%E5%8D%A1&quot; aria-label=&quot;所以选什么信用卡 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;所以，选什么信用卡？&lt;/h3&gt;
&lt;p&gt;按权益简单且不完全分类的话，新加坡的信用卡大概可以分成两类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;返现（Cashback）信用卡&lt;/li&gt;
&lt;li&gt;积分里程（Points &amp;#x26; Miles）信用卡&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你和我一样，&lt;strong&gt;单身年轻低消费，也不热衷于飞来飞去和住酒店&lt;/strong&gt;，那么，Cashback 类型的信用卡大概是更佳的选择。省去了积分里程的缓慢积攒与过期失效，而是简单直接的消费返现。&lt;/p&gt;
&lt;p&gt;而就 Cashback 类型而言，大体上依旧可以做细分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;无门槛无上限的绝对返现（Absolute Cashback)&lt;/li&gt;
&lt;li&gt;带有消费门槛（比如每月最低消费 600 新币），消费类别（比如仅限于超市购物）甚至特定商户（比如仅限于某些超市品牌），以及返现上限（比如每月封顶 20 新币）的返现&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;后者听上去似乎充满了限制，让人很不爽？是的。但大部分卡属于后者，往往会拥有更高的返现比例，往往会&lt;strong&gt;特别针对了一部分人群的消费习惯进行优化&lt;/strong&gt;，因而特定条件下可以达到 &lt;strong&gt;10% 以上&lt;/strong&gt;的消费返现，相当诱人。因此，如果你有一些时间和精力，不妨使用上述三个网站稍微浏览一些这些信用卡的规则，如果有和自己平常消费习惯匹配的卡，那将是最为理想的选择。&lt;/p&gt;
&lt;p&gt;而如果你不想付出太多的时间与精力，又或者你像我一样，单身年轻低消费，&lt;strong&gt;无门槛无上限的的绝对返现卡则是简单省心的不错选择&lt;/strong&gt;。这类卡一般来说不限制消费的类别（当然，少数特定消费类别可能会被排除），也不会设置每月返现的上限，而是简简单单地给出一个返现比例（如 1.6%，且新用户前几个月一般享有更高的比例，如 4.5%），适用于所有满足条件的消费账单。这里简单列出这一类别的几张信用卡（其实屈指可数）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moneysmart.sg/credit-cards/american-express-true-cashback-card&quot;&gt;American Express True Cashback Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moneysmart.sg/credit-cards/uob-absolute-cashback-card&quot;&gt;UOB Absolute Cashback Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moneysmart.sg/credit-cards/citi-cashback-plus-card&quot;&gt;Citi Cash Back+ Mastercard®&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外，上面列出的前两张卡还具有某种隐藏的福利：这两张卡的无门槛返现&lt;strong&gt;几乎支持所有的消费类别&lt;/strong&gt;，如保险费用、水电账单这种大部分卡不支持的类别；且适用于 &lt;strong&gt;GrabPay 钱包充值&lt;/strong&gt;，倘若&lt;strong&gt;叠加&lt;/strong&gt; GrabPay 本身的 1.2% 消费返现，也算是相当不错的比例了。（这点在之后的移动支付章节会再详述。）&lt;/p&gt;
&lt;p&gt;最后，我的个人建议是，可以申请两到三张信用卡：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一张无门槛返现信用卡（简单粗暴，适用于大部分消费，且可以叠加 GrabPay）&lt;/li&gt;
&lt;li&gt;一张比较贴合你日常消费习惯的信用卡（譬如，如果你经常去某家超市购物，那不妨办一张对这家超市有额外返现的信用卡）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;如何申请&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%A6%82%E4%BD%95%E7%94%B3%E8%AF%B7&quot; aria-label=&quot;如何申请 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;如何申请？&lt;/h3&gt;
&lt;p&gt;最基本的注意事项是：尽量在有几个月的&lt;strong&gt;工资发放记录&lt;/strong&gt;之后再申请信用卡。不少银行会期望申请者提供&lt;strong&gt;最近三个月的工资单和银行账单&lt;/strong&gt;，申请者从而可以较为容易地通过申请，并获得较高的信用额度（一般上限是月工资的四倍）。但如果你像我一样想要尽早拿到信用卡，或者并不是很在意额度的高低，那可以在&lt;strong&gt;收到第一个月工资之后&lt;/strong&gt;开始申请，依旧是可以顺利通过的。&lt;/p&gt;
&lt;p&gt;在申请信用卡时，除了身份证明和居住地址证明（这两者想必你已经在之前开立银行账户时解决了），还需要提供&lt;strong&gt;工作和收入证明等文件&lt;/strong&gt;。依旧是以 &lt;a href=&quot;https://www.dbs.com.sg/personal/cards/cards-application-checklist.page&quot;&gt;DBS 的信用卡申请材料&lt;/a&gt; 为例：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a) Valid Passport (with at least 6 months validity)&lt;/p&gt;
&lt;p&gt;b) Employment Pass (with at least 6 months validity)&lt;/p&gt;
&lt;p&gt;c) Latest Income Tax Notice of Assessment&lt;/p&gt;
&lt;p&gt;d) Latest computerised payslips&lt;/p&gt;
&lt;p&gt;e) Company letter certifying employment and salary in SGD (dated within last 3 months from date of card application) + Copy of Staff Pass&lt;/p&gt;
&lt;p&gt;f) A copy of your Telecommunication or Utility Bill (For new DBS/POSB Bank customers only)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;而结合我的实际申请体验，简单来说，&lt;strong&gt;主要需要准备公司出具的雇佣证明（最好能带有薪资）、最近几个月的工资单，以及偶尔可能会被要求提供的最近几个月的银行结单（需要有工资发放记录）&lt;/strong&gt;。另外，向工资账户所在的同一银行申请信用卡往往会简单许多，可以省去不少额外的证明文件，也大概率会有更高的额度。&lt;/p&gt;
&lt;p&gt;最后，如果真的要申请信用卡，记得去前面提到的三个网站浏览对比：不同时期，不同网站，会提供不同力度的新用户促销活动。有时候，申请一张信用卡并满足一定的消费要求，可以获得数百新币的现金奖励，千万别错过。&lt;/p&gt;
&lt;h2 id=&quot;数字支付&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%95%B0%E5%AD%97%E6%94%AF%E4%BB%98&quot; aria-label=&quot;数字支付 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;数字支付&lt;/h2&gt;
&lt;p&gt;不同于国内的微信支付、支付宝的两大巨头对立与无处不在的二维码，在新加坡，数字支付依旧处于「野蛮竞争」的发展阶段，在很多场景下，并不是主流（甚至不是可选）的支付手段。但也正因如此，探索新加坡的数字支付，尽量做到无现金，对我来说是一件很有趣的事情。&lt;/p&gt;
&lt;h3 id=&quot;网上购物&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%BD%91%E4%B8%8A%E8%B4%AD%E7%89%A9&quot; aria-label=&quot;网上购物 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;网上购物&lt;/h3&gt;
&lt;p&gt;在新加坡进行网上购物，不论是 Shopee、Lazada 之类的电商，还是 Grab、Deliveroo 之类的外卖，某种意义上其实和国内没啥区别：添加借记卡/信用卡（之后统称为银行卡）到钱包，然后支付即可。但不同之处在于，&lt;strong&gt;不同的平台往往有各自的钱包服务&lt;/strong&gt;，而非普适大一统的微信支付、支付宝。因此，网上支付可以大致分成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每次直接使用银行卡，输入卡号、CVV、有效日期（这是比较传统的支付方式，如水电账单支付）&lt;/li&gt;
&lt;li&gt;平台特定的 ShopeePay、GrabPay 等钱包，抑或提前向钱包充值，抑或付款时直接从银行卡中扣款（适用于 Shopee、Grab、Lazada 等新兴 APP）&lt;/li&gt;
&lt;li&gt;Paypal 支付（十分类似于微信支付、支付宝的体验），但在新加坡的适用范围很有限、主要是一些国际化（此处特指欧美）的平台会支持&lt;/li&gt;
&lt;li&gt;Google Pay 与 Apple Pay（体验最为良好，适用于部分手机 APP，如 Shopee）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;或许有点复杂？是的。但不管怎样，在设置好 Google Pay（包括 Apple Pay，下同）和常用 APP 的支付手段（ShopeePay，GrabPay）之后，整体体验还算良好，能够应对多数场景。而且从某种角度来看，相比于两大巨头垄断，这也算是某种自由竞争市场吧……&lt;/p&gt;
&lt;h3 id=&quot;线下支付&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%BA%BF%E4%B8%8B%E6%94%AF%E4%BB%98&quot; aria-label=&quot;线下支付 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;线下支付&lt;/h3&gt;
&lt;p&gt;相比于网上购物，线下支付的复杂度似乎又要更高一些，不同的商家所接受的支付方式形形色色。大致可以分类如下：&lt;/p&gt;
&lt;h4 id=&quot;1-只接受现金&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%E5%8F%AA%E6%8E%A5%E5%8F%97%E7%8E%B0%E9%87%91&quot; aria-label=&quot;1 只接受现金 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 只接受现金&lt;/h4&gt;
&lt;p&gt;作为一个依赖现金的社会，新加坡有&lt;strong&gt;许多商家只接受现金支付&lt;/strong&gt;，醒目地贴着「Cash Only」。不过，由于移动支付的普及，稍微有些规模的商家都会接受除了现金之外的支付手段，一般仅仅是&lt;strong&gt;比较小或者比较传统的商家&lt;/strong&gt;才会只接受现金，如食阁的小商贩。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/cashonly-sign.webp&quot; alt=&quot;Cash Only&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;2-只接受现金nets-以及-paynow-等现金性质的支付手段&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%E5%8F%AA%E6%8E%A5%E5%8F%97%E7%8E%B0%E9%87%91nets-%E4%BB%A5%E5%8F%8A-paynow-%E7%AD%89%E7%8E%B0%E9%87%91%E6%80%A7%E8%B4%A8%E7%9A%84%E6%94%AF%E4%BB%98%E6%89%8B%E6%AE%B5&quot; aria-label=&quot;2 只接受现金nets 以及 paynow 等现金性质的支付手段 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. 只接受现金，NETS 以及 PayNow 等现金性质的支付手段&lt;/h4&gt;
&lt;p&gt;一个有趣的现象是，新加坡的许多商家（尤其是购物商场内的）都会配有 POS 机，理论上是可以支持信用卡消费的，但或许是出于费率考虑，不愿意承担信用卡的渠道费用（尤其是高昂的 AMEX），他们仅仅接受 NETS 或 PayNow 等&lt;strong&gt;现金性质的支付手段&lt;/strong&gt;。据我的不完全观察，这些商家一般处于中等规模，且利润率不是特别高，比如连锁的五金店、日用品店。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nets.com.sg/&quot;&gt;NETS&lt;/a&gt;，应该是&lt;strong&gt;新加坡本土的支付渠道&lt;/strong&gt;（至少我在国内和其他国家没有见到过），有点类似于香港的八达通。可以在便利店很方便地买到 NETS 储值卡，用现金或银行卡为其充值，可以用于公交地铁和各种接受 NETS 的商家消费，用途相当广泛。此外，新加坡的一些银行发行的借记卡或信用卡，如果带有 NETS 标记，并绑定了银行账户，也可以当作 NETS 卡使用，每次消费时直接从银行账户扣款。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://abs.org.sg/consumer-banking/pay-now&quot;&gt;PayNow&lt;/a&gt;，我理解为&lt;strong&gt;新加坡官方推行的移动支付工具，可以很方便地用来转账、扫码支付&lt;/strong&gt;。PayNow 本身没有独立的 APP，而是依附于各家银行而存在，是内嵌于银行 APP 的一个功能。而在用 PayNow 扫码支付时，则相当于直接从个人绑定的银行账户转账给商家，依旧是现金性质。顺便一提，如果在新加坡使用 Google Pay，&lt;strong&gt;其转账功能即是通过 PayNow 实现的，也支持用 Google Pay 进行 PayNow 扫码支付&lt;/strong&gt;。&lt;/p&gt;
&lt;h4 id=&quot;3-接受现金nets--paynow-以及信用卡&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-%E6%8E%A5%E5%8F%97%E7%8E%B0%E9%87%91nets--paynow-%E4%BB%A5%E5%8F%8A%E4%BF%A1%E7%94%A8%E5%8D%A1&quot; aria-label=&quot;3 接受现金nets  paynow 以及信用卡 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. 接受现金、NETS &amp;#x26; PayNow 以及信用卡&lt;/h4&gt;
&lt;p&gt;再上一些规模，如 FairPrice 超市、屈臣氏、小米之家（是的，新加坡有小米之家）、较贵的饭店等，这些商家的 POS 机都会支持信用卡支付。一般来说，VISA 和 MasterCard 是广泛被接受的，而 AMEX 由于其格外高的费率，普及率稍微低一些。&lt;/p&gt;
&lt;p&gt;在这些商家，即可轻松地刷卡消费。如果将信用卡添加到 Google Pay，且手机支持 NFC 功能，可以&lt;strong&gt;直接使用 Google Pay 来进行无接触支付&lt;/strong&gt;，非锁屏状态下挥一挥手机即可，方便快捷，体验上明显优于国内的二维码支付（无论是扫码还是被扫码）。&lt;/p&gt;
&lt;p&gt;另外，如果你还记得之前提到的信用卡介绍，部分信用卡（如 DBS Live Fresh）针对 Google Pay 这种无接触支付（Contactless Payment）有着额外的返现（如 5%），方便快捷之余，还能一举两得地赚得返现。&lt;/p&gt;
&lt;h4 id=&quot;4-二维码支付&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-%E4%BA%8C%E7%BB%B4%E7%A0%81%E6%94%AF%E4%BB%98&quot; aria-label=&quot;4 二维码支付 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. 二维码支付&lt;/h4&gt;
&lt;p&gt;二维码支付和上述三个类别其实是&lt;strong&gt;正交的&lt;/strong&gt;：只接受现金的商家可能会接受二维码，支持信用卡的商家也可能不支持二维码，且 PayNow 即属于二维码支付。而且不同于国内，我在新加坡似乎没有见过&lt;strong&gt;被动式&lt;/strong&gt;的被扫码支付，而只见过&lt;strong&gt;主动&lt;/strong&gt;的扫码支付。而关于二维码，大致可以分成两类：&lt;/p&gt;
&lt;p&gt;一是各个支付软件的独立二维码，如前面提到的 GrabPay 和 PayNow，以及各家银行各自推行的支付 APP（如 DBS PayLah，但基本没啥使用的意义）。就我的观察而言，&lt;strong&gt;GrabPay 二维码在新加坡的普及程度尚可，尤其是各种餐饮商家&lt;/strong&gt;，如果提供了扫码支付，大概率是 GrabPay 的二维码（或者下述的万能码）；PayNow 也有一定的普及度，毕竟其是新加坡官方推行的支付手段。除此之外的其他二维码，往往都是个别出现，我一般直接无视，甚至宁愿回退到现金支付。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/grab-qr-code-at-itea.webp&quot; alt=&quot;奶茶店的 GrabPay 二维码&quot;&gt;&lt;/p&gt;
&lt;p&gt;二是新加坡政府推行的「万能二维码」。有多万能呢？见下图。可以看到，这样的二维码同时支持了&lt;strong&gt;数十种支付平台，甚至包括了国内的微信支付和支付宝&lt;/strong&gt;。这样的二维码，我主要在食阁商贩处见到，尤其是 Chinatown 的小商贩。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/super-qr-code-at-chinatown.webp&quot; alt=&quot;Chinatown 见到的万能二维码&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;5-公交地铁&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-%E5%85%AC%E4%BA%A4%E5%9C%B0%E9%93%81&quot; aria-label=&quot;5 公交地铁 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;5. 公交地铁&lt;/h4&gt;
&lt;p&gt;在新加坡，日常出行基本上完全依赖步行和公交地铁，因为打车实在太贵了。和国内城市的公交地铁系统类似，可以购买单次票，但出于便捷和省钱考虑，使用 NETS 卡或者银行卡是更推荐的选择。&lt;/p&gt;
&lt;p&gt;如前所述，可以在便利店或者其他地方购买并充值 &lt;strong&gt;NETS 储值卡（或者类似的 EZ-Link 卡）&lt;/strong&gt;，刷卡乘地铁。而如果有了银行卡（包括借记卡和信用卡），则可以&lt;strong&gt;直接刷银行卡&lt;/strong&gt;，省去了一张额外的 NETS 卡。当然，既然能用银行卡，Google Pay 自然也是可以的，过闸前只需要解锁手机，然后 NFC 一刷而过，体验相当顺畅。&lt;/p&gt;
&lt;h4 id=&quot;6-grabpay-与-grabpay-card&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#6-grabpay-%E4%B8%8E-grabpay-card&quot; aria-label=&quot;6 grabpay 与 grabpay card permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;6. GrabPay 与 GrabPay Card&lt;/h4&gt;
&lt;p&gt;最后，或许值得单独讨论一下 GrabPay，以及其配套的 GrabPay Card。&lt;/p&gt;
&lt;p&gt;在扫码支付的时候，不同于微信支付和支付宝可以直接从绑定的银行卡扣款，&lt;strong&gt;GrabPay 本质上是一个需要预先储值的钱包&lt;/strong&gt;，需要先从银行卡充值，然后才能支付给商家（当然，可以设置自动充值）。而就目前而言，GrabPay 支持&lt;strong&gt;无手续费从信用卡充值&lt;/strong&gt;，这意味着信用卡的适用范围得到了巨大的扩展。如果你像我一样，不喜欢从储蓄的银行账户消费，那这一点应该会很令你满意。而如果你使用的是无门槛返现信用卡，且其消费类别没有排除 GrabPay 充值，你还能获得相应的返现。&lt;/p&gt;
&lt;p&gt;而在扫码支付之外的场景，GrabPay 还提供了可以申请的&lt;strong&gt;实体卡&lt;/strong&gt;，&lt;a href=&quot;https://www.grab.com/sg/pay/card/grabpay/&quot;&gt;GrabPay Card&lt;/a&gt;。这是一张 MasterCard 的借记卡，刷卡消费时从绑定的 GrabPay 扣款。其好处在于，可以在需要银行卡的场景使用 GrabPay，叠加享受 GrabPay 提供的积分福利；且如果你的信用卡是 AMEX 等不怎么被支持的卡组织，这相当于将其转换成了广受支持的 MasterCard。&lt;/p&gt;
&lt;h3 id=&quot;我的建议&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%88%91%E7%9A%84%E5%BB%BA%E8%AE%AE&quot; aria-label=&quot;我的建议 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;我的建议&lt;/h3&gt;
&lt;p&gt;那么，在新加坡，既然有这么多种不同的支付手段，商家对其的支持范围也各异，该如何应对以尽量做到无现金呢？我的建议是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在有银行账户之前，使用现金和 NETS 储值卡应对大部分商家，而如果遇到万能二维码，则可以方便地使用微信支付或支付宝&lt;/li&gt;
&lt;li&gt;在有银行账户但无信用卡时，可以开通 GrabPay、申请 GrabPay Card
&lt;ul&gt;
&lt;li&gt;如果商家支持刷卡，使用 GrabPay Card 或者借记卡（可以添加到 Google Pay 使用）&lt;/li&gt;
&lt;li&gt;如果商家支持二维码支付，使用 GrabPay&lt;/li&gt;
&lt;li&gt;如果商家只支持 NETS 或 PayNow， 使用银行账户配备的借记卡（当然，需要支持 NETS），用 Google Pay 扫码 PayNow 支付&lt;/li&gt;
&lt;li&gt;准备少量现金，以应对 Cash Only，必要时通过借记卡在 ATM 随时取现&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;在有信用卡之后
&lt;ul&gt;
&lt;li&gt;大体思路同上，不过尽量用信用卡取代上述的借记卡，且可以综合消费场景选择最合适的信用卡&lt;/li&gt;
&lt;li&gt;如果信用卡有 NETS 标志，且绑定了银行账户，而没必要使用借记卡进行 NETS 支付&lt;/li&gt;
&lt;li&gt;如果信用卡绑定了银行账户，ATM 取现也可以直接用信用卡完成&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而就我目前的体验而言，&lt;strong&gt;Google Pay + GrabPay + 信用卡 NETS 支付基本上可以覆盖大部分的消费场景&lt;/strong&gt;，钱包里只准备了少量现金（大概每周消耗不到二十现金）。所以，从某种意义上说，如果愿意，在新加坡是可以做到很大程度的&lt;strong&gt;几乎&lt;/strong&gt;无现金生活的，而且我的个人观点是，NFC（如 Google Pay）是一种比扫码支付优雅很多的方式。不过，这就见仁见智了。&lt;/p&gt;
&lt;h2 id=&quot;个人保险&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%B8%AA%E4%BA%BA%E4%BF%9D%E9%99%A9&quot; aria-label=&quot;个人保险 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;个人保险&lt;/h2&gt;
&lt;p&gt;谈到个人金融，保险是不可避免的一部分。尤其是作为外国人，在新加坡，你我没法享受新加坡政府提供的医疗保障，&lt;strong&gt;一旦遇到任何意外或者疾病，只能完全靠自己和（公司和个人）保险&lt;/strong&gt;。因此，我的个人建议是，&lt;strong&gt;尽早&lt;/strong&gt;配置好个人保险。&lt;/p&gt;
&lt;h3 id=&quot;公司团险&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%85%AC%E5%8F%B8%E5%9B%A2%E9%99%A9&quot; aria-label=&quot;公司团险 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;公司团险&lt;/h3&gt;
&lt;p&gt;如果所在的公司尚且还算体面的话，那么大概率，公司会为所有的雇员购买集体保险，算是一项相当有用的员工福利了。不过，这样的公司团险的覆盖范围和额度往往各异，取决于公司的福利水平。以字节跳动为例（当然，这里不会透露具体的公司保险政策），和 AVIVA 合作，提供了较为不错的公司团险，覆盖了住院、意外和人寿，且保障范围较为全面，&lt;strong&gt;但如果细看保障额度，会发现相当局促&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Death Benefit: 10,000&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;作为收入还算体面的程序员，身价怎么看应该都不止一万新币吧。因此，为了提升自我身价，或者说，为了更全面更充分的保障，自行购买个人保险显得尤其重要。&lt;/p&gt;
&lt;p&gt;但需要特别说明的是，&lt;strong&gt;公司团险和个人保险是互补的，缺一不可&lt;/strong&gt;。公司团险的额度虽然有限，但在另一些方面，公司团险却有着无可取代的作用：譬如感冒发热之类的小毛病，基本上没有个人保险会覆盖（因为发生概率太高而且不可预知），但公司团险一般可以覆盖（因为根据大数定律，公司雇员够多则整体发生概率趋于稳定）。&lt;/p&gt;
&lt;p&gt;此外，如果你和我一样为字节跳动工作，那么友情提醒：公司每年可以报销一定额度以内的个人保险开销，可以帮助你省一大笔钱。&lt;/p&gt;
&lt;h3 id=&quot;基本的保险种类&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%9F%BA%E6%9C%AC%E7%9A%84%E4%BF%9D%E9%99%A9%E7%A7%8D%E7%B1%BB&quot; aria-label=&quot;基本的保险种类 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;基本的保险种类&lt;/h3&gt;
&lt;p&gt;关于保险的基础知识和概念，我推荐阅读这篇文章以及其指向的拓展链接：&lt;a href=&quot;https://blog.seedly.sg/working-adults-key-insurance-policies-singapore/&quot;&gt;An Ultimate Guide: Key Insurance Policies You Should Get In Singapore 2021&lt;/a&gt;，可以对新加坡的保险有一个较为基础全面的认知。而如果你有听播客的习惯，也可以收听 &lt;a href=&quot;https://podcasts.apple.com/cn/podcast/%E4%BF%9D%E6%8C%81%E9%80%9A%E8%AF%9D/id1552714352&quot;&gt;保持通话&lt;/a&gt;：虽然讲述的内容是国内的保险行业，但其实很多内容是相通的。&lt;/p&gt;
&lt;p&gt;而简单来说，在我看来（浅薄的自我学习之后），比较基本且必要的种类有：&lt;/p&gt;
&lt;h4 id=&quot;住院险hospitalization&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BD%8F%E9%99%A2%E9%99%A9hospitalization&quot; aria-label=&quot;住院险hospitalization permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;住院险（Hospitalization）&lt;/h4&gt;
&lt;p&gt;不同于国内目前的廉价医疗，如果没有保险的话，&lt;strong&gt;新加坡的医疗体系很昂贵，仅仅靠自己是很难负担起住院医疗的费用，更别提较为优质的私立医院&lt;/strong&gt;。因此，住院险应该是最为必要的保险种类。&lt;/p&gt;
&lt;p&gt;在选择住院保险的时候，就我的经验而言，主要需要关注其适用的医院级别（什么等级的公立医院？是否包括私立医院？），以及作为外国人，其是否支持除新加坡的海外医疗（包括哪些国家？海外医疗的报销范围与额度？）。另外，住院保险的保费和年龄正相关，趁着年轻，尽早购买可以省一点钱。&lt;/p&gt;
&lt;h4 id=&quot;意外险personal-accident&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%84%8F%E5%A4%96%E9%99%A9personal-accident&quot; aria-label=&quot;意外险personal accident permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;意外险（Personal Accident）&lt;/h4&gt;
&lt;p&gt;如果说住院险关注的是&lt;strong&gt;医疗的手段&lt;/strong&gt;（如住院、手术），那么意外险则是从&lt;strong&gt;医疗的缘由&lt;/strong&gt;着眼。顾名思义，这主要覆盖日常生活中的各种意外：譬如运动骨折，如果没有严重到住院的程度，住院保险是不会发挥作用的，意外保险则显出其必要性。&lt;/p&gt;
&lt;p&gt;另外，意外保险的保费和年龄无关，毕竟意外发生的概率和年龄并没有太大的关系。&lt;/p&gt;
&lt;h4 id=&quot;重疾险critical-illness与人寿险termwhole-life&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%87%8D%E7%96%BE%E9%99%A9critical-illness%E4%B8%8E%E4%BA%BA%E5%AF%BF%E9%99%A9termwhole-life&quot; aria-label=&quot;重疾险critical illness与人寿险termwhole life permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;重疾险（Critical Illness）与人寿险（Term/Whole Life）&lt;/h4&gt;
&lt;p&gt;重疾与人寿其实是两种保险：前者在确诊重疾时赔付，后者在身故时赔付，但都是一次性赔付固定数目。但对我而言，重疾险是作为人寿险的附加条款（Rider）购买的，且两者较为类似，故在此一并讨论。而按照相似的逻辑，这两种保险保障的是&lt;strong&gt;人身健康本身，无关医疗&lt;/strong&gt;：只要身故或者确诊重疾，不论是否接受医疗，不论接受何种医疗，便会赔付。&lt;/p&gt;
&lt;p&gt;一个十分值得思考的问题是，是购买&lt;strong&gt;定期寿险（Term Life）还是终身寿险（Whole Life）&lt;/strong&gt;？前者可以自行确定一个固定的年限，比如保障到六十岁，每年交费，六十岁后失效；后者终身有效，需要支付一定年限的保费，之后不必支付。关于两者的讨论有很多，也没有一定的结论，所以需要个人权衡取舍。可以参考这篇文章：&lt;a href=&quot;https://blog.seedly.sg/term-life-or-whole-life-insurance-which-get/&quot;&gt;Working Adult Guide: Term Life Or Whole Life Insurance, Which Should I Get?&lt;/a&gt;。当然，还有第三种选择：带有投资性质的 ILP（Investment-Linked Policy），不过由于我的个人偏好，倾向于将保险作为纯粹的风险抵御工具，而不希望带上投资属性，便不做介绍了。&lt;/p&gt;
&lt;h3 id=&quot;那么选哪家保险公司的哪种保险方案&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%82%A3%E4%B9%88%E9%80%89%E5%93%AA%E5%AE%B6%E4%BF%9D%E9%99%A9%E5%85%AC%E5%8F%B8%E7%9A%84%E5%93%AA%E7%A7%8D%E4%BF%9D%E9%99%A9%E6%96%B9%E6%A1%88&quot; aria-label=&quot;那么选哪家保险公司的哪种保险方案 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;那么，选哪家保险公司的哪种保险方案？&lt;/h3&gt;
&lt;p&gt;我不知道。而且购买保险是一件相当&lt;strong&gt;私人且个性化&lt;/strong&gt;的事情，不同人有不同的需求和偏好，自己做功课是一件必不可少的事。&lt;/p&gt;
&lt;p&gt;不过，在我购买保险的过程中，接触了不少公司的保险中介，和他们的交谈过程中，我其实额外学习了解了很多新加坡的医疗和保险体系。我的总体感受是，我接触的中介都还算专业，而且新加坡作为金融中心，保险行业竞争相当充分（依旧是你能想象国内的一个城市有近十家保险公司吗？），甚至有身在大陆的国人慕名前来购买保险，不同公司的保险方案其实大同小异，性价比都还算不错，没有太大的差异。&lt;/p&gt;
&lt;p&gt;如果你打算购买保险，我的唯一建议是：借助 Seedly 等网站做足功课，然后多约几个不同公司的保险中介，花时间和他们多聊一聊，选择你觉得靠谱的那一个。&lt;/p&gt;
&lt;h2 id=&quot;投资理财&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%8A%95%E8%B5%84%E7%90%86%E8%B4%A2&quot; aria-label=&quot;投资理财 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;投资理财&lt;/h2&gt;
&lt;p&gt;投资理财是一个相当有趣也相当复杂的话题，&lt;strong&gt;作为投资的初学者（俗称「韭菜」）&lt;/strong&gt;，在此，我没有太多经验可以分享，仅仅简单分享我的个人体验。&lt;/p&gt;
&lt;h3 id=&quot;低利率&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BD%8E%E5%88%A9%E7%8E%87&quot; aria-label=&quot;低利率 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;低利率&lt;/h3&gt;
&lt;p&gt;首先，之所以需要投资，是因为在新加坡，&lt;strong&gt;银行存款的利息低到可以忽略&lt;/strong&gt;。如前所述，即便各种 bonus 利率叠加，对于一般人，能获得的年化利率也不过 1.0% 左右，考虑到通货膨胀的因素，几乎可以认为没有任何收益。且作为没有身份的外国人，也无法享受新加坡政府提供的养老储蓄计划（利率大概会有 3% - 4%，不过比较难提前取出）。&lt;/p&gt;
&lt;p&gt;而另一方面，至少就我的学习探索下来，新加坡没有类似国内类似余额宝、朝朝盈等方便无脑且（几乎）零风险的投资产品。诚然，可以购买 Moeny Market Fund，本质上就是货币基金，但我个人觉得&lt;strong&gt;购买起来不是很方便（比起国内方便的支付宝买基金）&lt;/strong&gt;。当然，这仅仅是我作为初学者的简单观察，欢迎指正。&lt;/p&gt;
&lt;h3 id=&quot;自由市场&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%87%AA%E7%94%B1%E5%B8%82%E5%9C%BA&quot; aria-label=&quot;自由市场 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;自由市场&lt;/h3&gt;
&lt;p&gt;在新加坡，最大的好处是&lt;strong&gt;充分自由的金融市场&lt;/strong&gt;，没有外汇管制，有各种的投资选择。甚至，如果愿意的话，可以很方便地把新币转成人民币投入到余额宝中。&lt;/p&gt;
&lt;p&gt;相比于身在国内投资美股的万般阻碍，在新加坡可以十分方便地投资全球市场，开办一个股票账户（如 Tiger，Moomoo），即可投资新加坡、香港、美股市场的证券。其中，我觉得格外值得关注的是，新加坡交易所上市交易的各种 ETF 以及 REITs，风险相对较可控，收益看上去还算稳定。不过依旧是不构成投资建议，毕竟证券交易是一件很有风险的事情。&lt;/p&gt;
&lt;h3 id=&quot;roboadvisor&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#roboadvisor&quot; aria-label=&quot;roboadvisor permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;RoboAdvisor？&lt;/h3&gt;
&lt;p&gt;有趣的是，在新加坡，&lt;a href=&quot;https://blog.moneysmart.sg/invest/robo-advisors-singapore/&quot;&gt;智能投顾（RoboAdvisor）&lt;/a&gt; 相当流行（或者说，广告宣传做得足够猛烈，让我觉得其相当流行）。我没有对其做比较深入的研究，但大体上是通过算法来进行资产配置，并可以针对不同的风险等级和市场偏好进行选择。&lt;/p&gt;
&lt;p&gt;如果不想在投资上投入过多的时间与精力，不妨试一试。&lt;/p&gt;
&lt;h2 id=&quot;最后&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9C%80%E5%90%8E&quot; aria-label=&quot;最后 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;最后&lt;/h2&gt;
&lt;p&gt;这篇文章断断续续地写了两个礼拜，从一开始的一时兴起想要分享个人经验，到差不多写完时的深感不足：这份指南实在不是很全面靠谱，甚至有点称不上指南。所以，十分欢迎大家在评论区留言指正，让这份不全面不靠谱的指南变得更加全面而靠谱，可以帮助到更多和当初的我一样的朋友们，初来新加坡而探索个人金融世界。&lt;/p&gt;
&lt;p&gt;最后的最后，如果你还没有来新加坡，但是对在新加坡工作有兴趣，欢迎和我联系，或许，将来有机会可以在新加坡做同事也未可知。至于怎么联系我，请看左边栏。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[为什么用 Go 访问某网站始终会 503 Service Unavailable ？]]></title><description><![CDATA[记一次耗费了我三天精力，但是相当有趣的 Debug 经历]]></description><link>https://www.zackwu.com/posts/2021-03-14-why-i-always-get-503-with-golang/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2021-03-14-why-i-always-get-503-with-golang/</guid><pubDate>Sun, 14 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;发生了什么事&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8F%91%E7%94%9F%E4%BA%86%E4%BB%80%E4%B9%88%E4%BA%8B&quot; aria-label=&quot;发生了什么事 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;发生了什么事？&lt;/h2&gt;
&lt;p&gt;得益于近年来网络资料的宣传普及与现代编程语言的强大标准库，编程爬取网站的内容（即写爬虫）成为了一件相当简单的事情：无非是调用各个编程语言自带的网络库，最多再手动设置一些参数以尽可能地伪装成正常用户以绕开网站的反爬限制。对于熟悉 Python 的同学，上面说的内容甚至不过只是两三行代码的事情。&lt;/p&gt;
&lt;h3 id=&quot;问题描述&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%97%AE%E9%A2%98%E6%8F%8F%E8%BF%B0&quot; aria-label=&quot;问题描述 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;问题描述&lt;/h3&gt;
&lt;p&gt;然而，几天前，我却遇到了一个相当棘手的爬虫问题（&lt;a href=&quot;https://github.com/miniflux/v2/issues/1047&quot;&gt;Github Issue&lt;/a&gt;）：&lt;a href=&quot;https://www.bundesregierung.de/breg-en&quot;&gt;某一个神奇的网站&lt;/a&gt;，用户可以正常访问，用 Python 等语言写的（简易）爬虫可以正常访问，甚至直接用 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 也能正常访问，唯独用 Go 语言写的（简易）爬虫始终被 &lt;code class=&quot;language-text&quot;&gt;503 Service Unavailable&lt;/code&gt; 拒之门外，尝试多种伪装策略（如 &lt;code class=&quot;language-text&quot;&gt;User-Agent&lt;/code&gt;）均以失败告终。更加神奇的是，如果让 Go 发出的请求经由本机的某个代理（比如为了抓包观察），那么一切又能正常工作了（这一点是我在调试过程中发现的，一开始并不知道）。&lt;/p&gt;
&lt;p&gt;如果你读了我的上述描述，和当时的我一样觉得不可思议：难道编程语言还有高下之分？这个网站歧视某些编程语言？同时又有些跃跃欲试的想法，不妨先停止阅读，花一点时间，参考我下面贴出的代码，尝试复现并解决这个神奇的问题。&lt;/p&gt;
&lt;h3 id=&quot;复现代码&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%A4%8D%E7%8E%B0%E4%BB%A3%E7%A0%81&quot; aria-label=&quot;复现代码 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;复现代码&lt;/h3&gt;
&lt;p&gt;首先是始终会得到 &lt;code class=&quot;language-text&quot;&gt;503 Service Unavailable&lt;/code&gt; 错误的 Go 语言代码：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	resp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://www.bundesregierung.de/breg-en&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Output:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 503 Service Temporarily Unavailable&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后是普普通通而且仅有 3 行，但是可以正常工作的 Python 代码：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; urllib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request
resp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urllib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urlopen&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://www.bundesregierung.de/breg-en&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Output:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# 200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最后是简单直接的 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 命令：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# -s: silent mode to hide progress meter or error messages&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# -o: redirect output to file (any write to /dev/null is discarded)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# -w: display certain information on completion (http_code is a variable)&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; /dev/null &lt;span class=&quot;token parameter variable&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%{http_code}&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.bundesregierung.de/breg-en&quot;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;我是如何调试的&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%88%91%E6%98%AF%E5%A6%82%E4%BD%95%E8%B0%83%E8%AF%95%E7%9A%84&quot; aria-label=&quot;我是如何调试的 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;我是如何调试的？&lt;/h2&gt;
&lt;h3 id=&quot;http-headers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#http-headers&quot; aria-label=&quot;http headers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;HTTP Headers&lt;/h3&gt;
&lt;p&gt;在遇到这个问题时，我的第一反应是：对方网站肯定有某种反爬虫机制。然而，作为一个没写过多少爬虫代码的小白，我又实在感到有些费解：既然如此，为何用 Python 写的爬虫简陋不堪却能正常工作呢？&lt;/p&gt;
&lt;p&gt;或许是这个网站针对性地不让 Go HTTP Client 访问？假如是这样，在大多数情况下，服务器是通过 &lt;code class=&quot;language-text&quot;&gt;User-Agent&lt;/code&gt; 等 HTTP Headers 来识别请求的来源，那么，我只需要手动设置 HTTP Headers 进行伪装，似乎就可以绕开这样的检测？为了验证这个猜想，我做了两个实验：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把 Go HTTP Client 伪装成 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt;：结果依旧是 &lt;code class=&quot;language-text&quot;&gt;503&lt;/code&gt;。（需要说明的是，由于 Go HTTP Client 会自动给 Headers 加上 &lt;code class=&quot;language-text&quot;&gt;Accept-Encoding: gzip&lt;/code&gt;，所以此处的 Headers 实际上不完全和 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 一样，不过在此也无关紧要了，原因见后文的进一步实验。）&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http/httputil&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	client &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Client&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.bundesregierung.de/breg-en&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;User-Agent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;`curl/7.68.0`&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Header&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	resp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Do&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	requestDump&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; httputil&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DumpRequestOut&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestDump&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Output:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// GET /breg-en HTTP/1.1&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Host: www.bundesregierung.de&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// User-Agent: curl/7.68.0&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Accept: */*&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Accept-Encoding: gzip&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// &lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 503 Service Temporarily Unavailable&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;把 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 伪装成 Go HTTP Client：可以正常工作。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.bundesregierung.de/breg-en&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;User-Agent: Go-http-client/1.1&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Accept-Encoding: gzip&quot;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; GET /breg-en HTTP/1.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Host: www.bundesregierung.de
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Accept: */*
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; User-Agent: Go-http-client/1.1
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; Accept-Encoding: &lt;span class=&quot;token function&quot;&gt;gzip&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; OK
&lt;span class=&quot;token comment&quot;&gt;# ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;面对以上奇怪的实验结果，我起初怀疑是我有所疏漏，然而反复检查之后，我不得不承认 Go 和 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 发出的请求在 HTTP 层面确实完全一致。那么，我所得出的结论只能是：请求返回 &lt;code class=&quot;language-text&quot;&gt;503&lt;/code&gt; 并不是因为 Go HTTP Client 所发出的 HTTP 请求具有某种特征。然而「同样」的 HTTP 请求，由 Go HTTP Client 发出会被 &lt;code class=&quot;language-text&quot;&gt;503&lt;/code&gt;，由 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 发出就能正常得到响应，难道是 Go 本身存在问题？&lt;/p&gt;
&lt;h3 id=&quot;go-nethttp&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#go-nethttp&quot; aria-label=&quot;go nethttp permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Go &lt;code class=&quot;language-text&quot;&gt;net/http&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;本着「大胆假设，小心求证」的原则，既然同样的请求由 Go 和 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 发出会得到不同的结果，那我便大胆地怀疑是 Go 的 HTTP 标准库 &lt;code class=&quot;language-text&quot;&gt;net/http&lt;/code&gt; 存在问题（似乎过于大胆了……）:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/go-net-twitter.png&quot; alt=&quot;My Twitter Screenshot&quot;&gt;&lt;/p&gt;
&lt;p&gt;然而，在埋头扎进 &lt;code class=&quot;language-text&quot;&gt;net/http&lt;/code&gt; 的源码几个小时之后，虽然我通过读代码+断点调试了解到了不少其内部实现细节，然而面对庞杂的代码库，实在有些大海捞针的无力感。另一方面，在冷静下来之后，我倾向于相信 Go 的 HTTP 标准库本身并没有与此相关的 Bug，毕竟这是一个广泛使用且成熟的标准库。另外，至少从概率上来说，问题出在其他地方的可能性会更大一些。&lt;/p&gt;
&lt;h3 id=&quot;fiddler-抓包&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#fiddler-%E6%8A%93%E5%8C%85&quot; aria-label=&quot;fiddler 抓包 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Fiddler 抓包&lt;/h3&gt;
&lt;p&gt;稍加思索，对方服务器必然是通过某种特征区分源于 Go 和 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 的请求。既然应用层的 HTTP 请求本身没有特征，难道是其下的传输层特征被识别？然而 TCP 栈更多是由操作系统提供，Go 和 &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; 的 TCP 请求在此层面似乎也没有什么区别，不太可能因此被区分。至于更往下的网络层、传输层和物理层，就更加不具有现实可能性了。&lt;/p&gt;
&lt;p&gt;一切似乎陷入了僵局？万般无奈之下，尽管没有报太大的指望，但是我想到了 &lt;a href=&quot;https://www.telerik.com/fiddler&quot;&gt;Fiddler&lt;/a&gt; 这款抓包工具，试图抓包研究请求的细微差异。只需要让 Go 发出的请求经由 Fiddler 提供的代理：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Setenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;HTTPS_PROXY&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;127.0.0.1:8866&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Fiddler&apos;s proxy address&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;由于对方网站采用了 HTTPS 协议，单纯地经由代理只能捕捉到 TLS 的握手请求，而无从得知 HTTPS 请求本身。好在 Fiddler 提供了相应的功能，在信任其证书之后，便可开启 Capture HTTPS trafic 功能。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/fiddler-https.png&quot; alt=&quot;Fiddler HTTPS&quot;&gt;&lt;/p&gt;
&lt;p&gt;然而此时，神奇的现象出现了：原本还是 &lt;code class=&quot;language-text&quot;&gt;503&lt;/code&gt; 的请求，在经由 Fiddler 代理之后，居然奇迹般地返回了 &lt;code class=&quot;language-text&quot;&gt;200&lt;/code&gt; 正常响应！不由得让我感到十分振奋（毕竟这证明了 Go 本身发出的请求并没有问题，是可以正常被服务器处理的），同时又无比费解，为什么同样的请求经过代理转发就能正常响应呢？&lt;/p&gt;
&lt;p&gt;为了探寻原因，我试着关闭了 Fiddler 的 Capture HTTPS trafic 功能，结果又恢复了 &lt;code class=&quot;language-text&quot;&gt;503&lt;/code&gt; 错误。&lt;/p&gt;
&lt;p&gt;也就是说，如果 Fiddler 仅仅是转发 HTTPS 请求，那么 &lt;code class=&quot;language-text&quot;&gt;503&lt;/code&gt; 依旧；而如果作为中间人，拦截 HTTPS 请求，解码查看内容之后再重新发送，一切就能 &lt;code class=&quot;language-text&quot;&gt;200&lt;/code&gt; 正常工作。&lt;/p&gt;
&lt;p&gt;所以，两者的区别在哪里？TLS。&lt;/p&gt;
&lt;h3 id=&quot;tls&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tls&quot; aria-label=&quot;tls permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TLS&lt;/h3&gt;
&lt;p&gt;虽然 HTTP 请求本身一样（正如我一开始所做的实验），但是由于 Fiddler 与 Go HTTP Client 的 TLS 客户端实现上的差异，在 TLS 握手阶段，二者的请求（比如 Client Hello 请求）存在区别，因而导致了不同的响应。&lt;/p&gt;
&lt;p&gt;为了确定我的这个猜想，我使用 &lt;a href=&quot;https://www.wireshark.org/&quot;&gt;Wireshark&lt;/a&gt; 捕获了两者的 Client Hello 握手请求：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go HTTP Client 的默认 TLS 握手 Client Hello 请求：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;0000   16 03 01 01 1f 01 00 01 1b 03 03 db ea 2e f0 b1   ................
0010   b1 ef 94 03 c6 03 6a 44 52 65 c3 5f 14 f4 76 89   ......jDRe._..v.
0020   7b 84 d3 05 d9 0d 31 e7 aa 55 b4 20 9e 91 91 f6   {.....1..U. ....
0030   dc eb 59 3b 34 b8 0d dd f8 8a 50 79 cd 42 38 14   ..Y;4.....Py.B8.
0040   b0 33 56 13 cd 19 db 2d 00 d9 19 0c 00 26 c0 2f   .3V....-.....&amp;amp;./
0050   c0 30 c0 2b c0 2c cc a8 cc a9 c0 13 c0 09 c0 14   .0.+.,..........
0060   c0 0a 00 9c 00 9d 00 2f 00 35 c0 12 00 0a 13 01   ......./.5......
0070   13 03 13 02 01 00 00 ac 00 00 00 1b 00 19 00 00   ................
0080   16 77 77 77 2e 62 75 6e 64 65 73 72 65 67 69 65   .www.bundesregie
0090   72 75 6e 67 2e 64 65 00 05 00 05 01 00 00 00 00   rung.de.........
00a0   00 0a 00 0a 00 08 00 1d 00 17 00 18 00 19 00 0b   ................
00b0   00 02 01 00 00 0d 00 1a 00 18 08 04 04 03 08 07   ................
00c0   08 05 08 06 04 01 05 01 06 01 05 03 06 03 02 01   ................
00d0   02 03 ff 01 00 01 00 00 10 00 0e 00 0c 02 68 32   ..............h2
00e0   08 68 74 74 70 2f 31 2e 31 00 12 00 00 00 2b 00   .http/1.1.....+.
00f0   09 08 03 04 03 03 03 02 03 01 00 33 00 26 00 24   ...........3.&amp;amp;.$
0100   00 1d 00 20 a5 ef 30 b8 03 04 8b 35 7c 43 d8 38   ... ..0....5|C.8
0110   3b 50 60 7e a6 8b a2 74 7e b6 18 ce 5d 32 af 5b   ;P`~...t~...]2.[
0120   2a ae ee 3e                                       *..&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Fiddler 发出 TLS 握手 Client Hello 请求：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;0000   16 03 03 01 7d 01 00 01 79 03 03 60 4e 05 ed b3   ....}...y..`N...
0010   96 19 ea 68 24 d6 20 e5 6a 96 7d 1b 17 09 91 77   ...h$. .j.}....w
0020   ca c6 03 92 f7 e5 a2 8a 5d 76 10 00 00 2a c0 2c   ........]v...*.,
0030   c0 2b c0 30 c0 2f 00 9f 00 9e c0 24 c0 23 c0 28   .+.0./.....$.#.(
0040   c0 27 c0 0a c0 09 c0 14 c0 13 00 9d 00 9c 00 3d   .&apos;.............=
0050   00 3c 00 35 00 2f 00 0a 01 00 01 26 00 00 00 1b   .&amp;lt;.5./.....&amp;amp;....
0060   00 19 00 00 16 77 77 77 2e 62 75 6e 64 65 73 72   .....www.bundesr
0070   65 67 69 65 72 75 6e 67 2e 64 65 00 0a 00 08 00   egierung.de.....
0080   06 00 1d 00 17 00 18 00 0b 00 02 01 00 00 0d 00   ................
0090   14 00 12 04 01 05 01 02 01 04 03 05 03 02 03 02   ................
00a0   02 06 01 06 03 00 23 00 d0 82 b6 de 47 77 d7 cc   ......#.....Gw..
00b0   bc c9 08 b9 50 41 ae 7d 4b 7d a8 b8 5d 3f 6e 85   ....PA.}K}..]?n.
00c0   56 25 81 39 7b f0 79 c2 4d d9 88 41 ae ed 83 30   V%.9{.y.M..A...0
00d0   15 42 be de 3b 2e 4f ae 9f 29 44 3c 22 32 e3 84   .B..;.O..)D&amp;lt;&quot;2..
00e0   1a 39 79 5c 2c 7d bf 18 48 bf 86 fe 96 09 58 c1   .9y\,}..H.....X.
00f0   69 67 d4 b4 1e 4b bd 8b 33 29 0b 49 18 7f 36 e5   ig...K..3).I..6.
0100   2c fc 33 40 44 3d f2 8e 11 c8 e0 fd 91 cd 64 1b   ,.3@D=........d.
0110   95 66 b2 c8 a2 93 96 3f d3 28 4f ce bc 79 e3 37   .f.....?.(O..y.7
0120   2d c0 ab 87 35 78 97 5b 5f 37 81 c3 15 76 04 04   -...5x.[_7...v..
0130   2c 05 f2 59 be f3 c4 e7 51 bf 7a 83 56 9b 8d cc   ,..Y....Q.z.V...
0140   60 f5 d9 7b 00 a8 1b 09 35 88 44 97 c1 52 e5 4e   `..{....5.D..R.N
0150   ec e3 b8 cf e1 a3 a5 47 49 3a 2e f0 15 b7 86 f8   .......GI:......
0160   44 08 74 c1 47 44 3c 62 9e ea 30 27 28 2b 16 e5   D.t.GD&amp;lt;b..0&apos;(+..
0170   0c 9b ed 35 51 fd b4 19 47 00 17 00 00 ff 01 00   ...5Q...G.......
0180   01 00                                             ..&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;很明显，二者存在差异（至少长度不一样）。如果进一步查看的话，可以发现内部的差异主要在于 Cipher Suites 和 Extensions 两部分，以前者为例（事实上，最后的实验也表明这确实是对方服务器的检测指标）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go HTTP Client&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Cipher Suites (19 suites)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
    Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
    Cipher Suite: TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (0xc012)
    Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
    Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
    Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
    Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Fiddler&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Cipher Suites (21 suites)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
    Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
    Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;既然如此，很自然的想法便是：只需要自定义 Go HTTP Client 所采用的 Cipher Suites，而不是使用其默认值，即可绕开检测？根据上面的抓包结果，可以知道，Go 所采用的默认 Cipher Suites 有 19 个（取决于平台环境，此为我的环境下的默认值），其中 &lt;a href=&quot;https://github.com/golang/go/blob/88b8a1608987d494f3f29618e7524e61712c31ba/src/crypto/tls/common.go#L626&quot;&gt;最后 3 个为 TLS 1.3 专属，无法自定义&lt;/a&gt;，不过我们可以灵活调整前面的 16 个。最简单的想法是，不改变这些 Cipher Suites，但是改变它们的顺序，从而绕开简单的特征匹配：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;crypto/tls&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	defaultCipherSuites &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;uint16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0xc02f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc030&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc02b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc02c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xcca8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xcca9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc013&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc009&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;token number&quot;&gt;0xc014&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc00a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x009c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x009d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x002f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x0035&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc012&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0x000a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	client &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Client&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		Transport&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Transport&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			TLSClientConfig&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;tls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Config&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				CipherSuites&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaultCipherSuites&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; defaultCipherSuites&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NewRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.bundesregierung.de/breg-en&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	resp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Do&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;defer&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Output:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 200 OK&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;大功告成！&lt;/p&gt;
&lt;p&gt;看来一切的根源确实在于 Go HTTP Client 所采用的默认 TLS Cipher Suites，由于其过于特殊，被对方服务器视作了某种检测特征，据此对请求返回 &lt;code class=&quot;language-text&quot;&gt;503 Service Unavailable&lt;/code&gt;，只需要人为改变 Cipher Suites，便可以轻松绕开这样的检测。&lt;/p&gt;
&lt;h2 id=&quot;尾声&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%B0%BE%E5%A3%B0&quot; aria-label=&quot;尾声 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;尾声&lt;/h2&gt;
&lt;p&gt;在耗费我三天的精力之后，我终于从根源上发掘出了问题的起源，并找到了简单的应对措施。虽然中途绕了好些弯路（比如一开始反复检查 HTTP Headers，中途扎进源代码的阅读中等），但是我觉得我的时间并没有被浪费，故写这篇文章，记录我的探索和实验经历。&lt;/p&gt;
&lt;p&gt;最后，当我发现问题出在 Cipher Suites 之后，我猛然间想起，其实早在约一年前，我已然在别处听闻过类似的机制：&lt;a href=&quot;https://github.com/v2ray/discussion/issues/704&quot;&gt;v2ray 的 TLS 流量可被简单特征码匹配精准识别（附 PoC)&lt;/a&gt;。只可惜当时的我对此不过是匆匆一瞥，没有太关注其细节，否则应该会早点跳出这次的坑，而不至于在坑中反复求索。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[二十一岁，直面选择，一往无前]]></title><description><![CDATA[于我而言，二十一岁的关键词是「选择」。经历了痛苦的纠结，但也笃定了未来的方向。]]></description><link>https://www.zackwu.com/posts/2020-11-26-choices-and-my-future/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2020-11-26-choices-and-my-future/</guid><pubDate>Thu, 26 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;也许多少年后在某个地方 / 我将轻声叹息把往事回顾 / 一片树林里分出两条路 / 而我选了人迹更少的一条 / 因此走出了这迥异的旅途。—— Robert Frost《未选择的路》&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;今天，又是我的生日。&lt;/p&gt;
&lt;p&gt;恍惚间，望着窗外和去年今日如出一辙的阴雨与夜色，感受着同样分明的寒冽与温暖，回想这一年的经历，其间有太多的无奈与纠结，即便如今一切尘埃落定，似乎也有些不真实的错觉。&lt;/p&gt;
&lt;p&gt;所以，还是写下来吧，用文字定格这一年与这一刻的思绪万千。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;二十一岁，我最大的关键词毫无疑问是「选择」。&lt;/p&gt;
&lt;p&gt;选择要不要读研，选择毕业后何去何从……似乎每一个都不是可以轻易做出的选择，而且会对我未来数年产生深远的影响，但不论如何，我最终做出了自己的选择，也即将在我所选择的路上一往无前。&lt;/p&gt;
&lt;p&gt;去年今日，我正在字节跳动经历我人生中的第一份实习，直至春节前的离职。本打算在春节之后去另一家公司开始新的实习，却因为不期而至的疫情而被迫在家度过了最长的寒假，打乱了原本的计划。直到夏天，才得以前往微软开启我的第二份实习，收获了和字节跳动在许多方面完全相反的实习体验。这两份实习经历，成为了我做选择的基石，让我最终能够坚定地做出选择。&lt;/p&gt;
&lt;p&gt;至于这两个选择的答案，不过是简简单单的两句话：在夏天我决定放弃读研而直接工作，在秋天我决定毕业后去阿里巴巴工作。可这些选择的背后呢？这些选择的未来呢？一切都复杂而混沌。&lt;/p&gt;
&lt;p&gt;第一个选择可以追溯到两年前，早有准备，因而在最终决定时并无太多纠结。&lt;/p&gt;
&lt;p&gt;十九岁的我在经历了简单的「科研体验」之后，对读研与学术研究产生了深深的自我怀疑。在其后的日子里，学习与生活之余，这个问题一直萦绕着我，而伴随着亲身实习体验与前人经验分享的交叠，我的答案渐渐明朗：我更适合做一个工程师，而非研究者，而且我也更想成为一个工程师。因此，在今年夏天，手握保研资格的我，没有参加任何夏令营，用 &lt;a href=&quot;/posts/2020-07-19-why-i-choose-to-work-after-graduation/&quot;&gt;《我为什么放弃保研，选择直接工作》&lt;/a&gt; 正式宣告了我的选择。&lt;/p&gt;
&lt;p&gt;第二个选择其实更为复杂，留给我的时间也更加少。&lt;/p&gt;
&lt;p&gt;决定毕业工作，我便开始了秋招。投递简历、笔试、面试，其间漫长的等待，以及收到 offer 之后的讨价还价，时间线自秋入冬，直至我生日的前一天，我正式寄出了我的三方协议，终于尘埃落定。自我反思，其实一开始的我有些下意识地在逃避这个选择：虽然没有广撒网地收割一大堆 offer，但是依旧没有提前想好自己究竟打算何去何从，而是投了好几家各有优劣的公司（给自己挖坑），直至收到带薪 offer 的那一刻，才被迫真正开始抉择。&lt;/p&gt;
&lt;p&gt;诚然，毕业后的第一份工作不过是职业生涯的开端，即便选错了，也有足够的空间可以腾挪调整。但对我来说，从各有优劣的公司中做出选择，依旧是一件困难的事情。在数日的痛苦纠结中，看似坚定清晰的决策逻辑被一次次推倒重建，我渐渐意识到，与其说我是在选择公司，不如说本质上我是在拷问自己究竟想要得到什么：是轻松的工作氛围吗？是到手的高薪水吗？还是安逸平稳的生活……自我认知是痛苦而困难的，甚至有些残酷：我不得不面对许多无奈的现实枷锁，感慨天不遂人愿。但一切也无可避免，直面选择是我唯一能做的，或早或晚，早些面对反而能给我更多的试错空间。&lt;/p&gt;
&lt;p&gt;或许有些朋友会对我最终选择去阿里巴巴工作有些讶异，我也同意这确实不是一个完美的选择。但如前所述，每家公司都有各自的优劣，没有完美的选项（事实上或许有，但可惜我手头上没有）。选择的过程便是取舍与妥协的过程，只能从中尽量找出与自身目标相契合的部分，并权衡其弊端是否在自身的接受范围内。于我而言，考虑种种因素（较为私人，此处就不展开叙述了），在现在的我看来，这已然是最不坏的选择。&lt;/p&gt;
&lt;p&gt;我曾数次设想一个场景，宛若梦魇：多年之后，生活不如意的我回首现今，后悔没能选择另一条道路。但反复纠结之后，我意识到我别无他法，只能坦然：谁又能预知未来呢？即便给我一万次机会，站在此时此刻，不借助更多的后验知识，我想，我也无法做出更好的选择。&lt;/p&gt;
&lt;p&gt;所以，直面选择之后，只管一往无前吧。&lt;/p&gt;
&lt;p&gt;不论如何，祝二十一岁的我生日快乐。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;注：由于身体不适，本文开始于 2020 年 11 月 26 日，实际完成于 11 月 27 日&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[校招面试不完全指南]]></title><description><![CDATA[在今年的校招中，我顺利通过了（几乎）所有我投递的公司的面试。如今秋招告一段落，总结我的经历，如何通过各大公司的技术岗位面试？这是一份不完全指南。]]></description><link>https://www.zackwu.com/posts/2020-10-05-an-incomplete-guide-to-campus-recruitment-interviews/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2020-10-05-an-incomplete-guide-to-campus-recruitment-interviews/</guid><pubDate>Mon, 05 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;背景&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%83%8C%E6%99%AF&quot; aria-label=&quot;背景 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;背景&lt;/h2&gt;
&lt;p&gt;在你看到这篇文章时，作为应届生的我，已经基本结束了今年的校招面试，并顺利地拿到了所有我有意向接受的公司 offer。&lt;/p&gt;
&lt;p&gt;在今年的校招中，我参加了不同公司的无数场面试。幸运的是，除了极个别的奇葩面试与面试官，我轻松且顺利地通过了几乎所有的面试。如今回顾我这大半年（从年初找暑期实习开始计算）的校招经历，虽然结果尚佳，但是其间倒也确实走了一些弯路，收获了一些经验与教训。&lt;/p&gt;
&lt;p&gt;故写此文，简单总结与分享，希望可以帮助到更多参加校招的同学。&lt;/p&gt;
&lt;p&gt;不过需要说明的是，这篇文章主要针对&lt;strong&gt;互联网公司的技术岗位校招&lt;/strong&gt;，对于非互联网企业、非技术岗位或者非校招，仅供参考。&lt;/p&gt;
&lt;h2 id=&quot;校招流程&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%A0%A1%E6%8B%9B%E6%B5%81%E7%A8%8B&quot; aria-label=&quot;校招流程 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;校招流程&lt;/h2&gt;
&lt;p&gt;如果你和大半年之前的我一样，尚未经历过校招，那么，你首先需要对校招流程有一个基本的了解。&lt;/p&gt;
&lt;p&gt;一般来说，按照时间线，校招流程主要有如下几个阶段（部分公司的校招流程可以跳过标有星号的阶段）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;网申 / 内推投递&lt;/li&gt;
&lt;li&gt;简历筛选&lt;/li&gt;
&lt;li&gt;笔试 *&lt;/li&gt;
&lt;li&gt;技术面试&lt;/li&gt;
&lt;li&gt;HR 面试 *&lt;/li&gt;
&lt;li&gt;发放 offer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接下来，按照上述划分，我分阶段地进一步介绍校招流程，并给出一些我的个人经验。&lt;/p&gt;
&lt;h3 id=&quot;网申--内推投递&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%BD%91%E7%94%B3--%E5%86%85%E6%8E%A8%E6%8A%95%E9%80%92&quot; aria-label=&quot;网申  内推投递 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;网申 / 内推投递&lt;/h3&gt;
&lt;p&gt;这一阶段是一切的开始。&lt;/p&gt;
&lt;p&gt;不论是网申投递，还是内推投递，虽然途径不同，但其作用都在于让你的简历进入校招的候选库中，以便 HR （或者其他人）从中挑选她/他觉得足够优秀的候选人，继续后面的流程。&lt;/p&gt;
&lt;p&gt;这一阶段的基本原则是：&lt;strong&gt;永远优先通过内推投递，除非万不得已，不要自己直接网申。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;虽然内推并不会像各种内推广告所言一样，具有起死回生的神奇效果，但是对于不少公司来说，内推的简历和网申的简历是区别对待的，前者优先级较高，甚至会在处理完前者之后才开始处理后者。另外，对于一些公司，直接通过网申投递没法「精准投递」想去的部门，而是由大部门统一分配，具有一定的随机性，这对于意向明确的同学是十分不利的。最后，考虑到近些年的内推泛滥，内推的意义有所贬值，已经成为人手一个的标配了，面对海量的内推简历，网申的优先级进一步降低。&lt;/p&gt;
&lt;p&gt;如何寻找内推？其实只要你的信息不是太闭塞，你完全不需要担心没有内推，而是需要考虑如何从海量内推的轰炸下选择一个合适的。&lt;/p&gt;
&lt;p&gt;最佳的内推人，应当是在意向部门工作的&lt;strong&gt;熟识&lt;/strong&gt;学长或者前辈，他们可以给你较好的内推反馈和帮助。如果没有，则退而求其次，在校内论坛等私域社交媒体上寻找内推，虽然不是熟人内推，但至少有一定的身份联结（比如校友）。再退一步，对于多数人而言，所谓的「内推」其实并非字面上的「内推」，而不过是投简历的一个渠道罢了，并没有啥特殊的。那么，可以关注各大广域社交媒体，比如 &lt;a href=&quot;https://www.nowcoder.com/discuss&quot;&gt;牛客网&lt;/a&gt;，上面有海量的内推广告贴：一般是部门员工或者 HR 所发，目的在于赚内推奖金或者完成 KPI。从中挑选你喜欢的，联系对方即可，但是不要对后续的内推反馈抱有太大的期望。&lt;/p&gt;
&lt;h3 id=&quot;简历筛选&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%AE%80%E5%8E%86%E7%AD%9B%E9%80%89&quot; aria-label=&quot;简历筛选 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;简历筛选&lt;/h3&gt;
&lt;p&gt;在投递简历之后，你的简历便进入了所谓的「简历池」中，等待 HR 从中捞取。&lt;/p&gt;
&lt;p&gt;由于这一阶段对我来说是一个黑盒，我并不了解其中的运作，在此便没有太多可以展开的。譬如如何撰写简历，如何包装自身的经历，这些都很重要，然而我并非 HR，对于这些就不探玄珠了，请参见别处的专业人士解答吧。&lt;/p&gt;
&lt;p&gt;不过有一点值得说明：筛选简历的一般是不负责技术的 HR，其筛选标准往往注重候选人的学历、实习经历等直观的硬指标，对于项目经历和技术能力等部分，仅仅略作观察以确保不会和岗位过于不匹配。&lt;/p&gt;
&lt;p&gt;此外，对于一些公司，内推确实可以提升简历筛选的通过率，甚至可以直接免筛通过。&lt;/p&gt;
&lt;h3 id=&quot;笔试&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%AC%94%E8%AF%95&quot; aria-label=&quot;笔试 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;笔试&lt;/h3&gt;
&lt;p&gt;并不是所有公司的校招流程都有笔试环节，或者即便有，也可以通过一些方法跳过（比如内推免笔试）。&lt;/p&gt;
&lt;p&gt;如果没法跳过笔试，那么，就面对它。不用担心，这并不困难。&lt;/p&gt;
&lt;p&gt;多数公司的笔试是 2 - 5 道算法题目，借助在线的测评平台（比如牛客网）举行，在一定的时间和空间限制下，根据通过的测试用例数量来给分。通常来说，笔试的算法题目难度不会太高，仅仅考察基本的数据结构和算法，比大学算法课程的平时作业难度还要低：毕竟这不是算法竞赛，实际工作中也不需要手写过于复杂的算法。&lt;/p&gt;
&lt;p&gt;如果你有一定的算法竞赛基础，那么这一部分对你来说应该轻而易举；如果你没有，就像我一样，也不必太担心，稍微刷题即可应对多数的题目。&lt;/p&gt;
&lt;p&gt;另外，少数公司的笔试还会有考察计算机基础知识的选择题，涉及计算机网络、数据库、编译原理、操作系统等计算机专业课，有点类似考研的题目。虽然难度不大，但是如果没有事先准备，还是有些吃力的。习惯于英文教材，且许久没有复习的我，险些在此翻车。&lt;/p&gt;
&lt;p&gt;最后，不必过于纠结笔试的成绩。很多时候，笔试只是一个门槛，通过就足够了，不一定非要做到很高的分数，毕竟后续的面试环节才是最重要的。&lt;/p&gt;
&lt;h3 id=&quot;技术面试&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%8A%80%E6%9C%AF%E9%9D%A2%E8%AF%95&quot; aria-label=&quot;技术面试 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;技术面试&lt;/h3&gt;
&lt;p&gt;这一阶段是校招中最重要的一部分，既决定了你最终能否拿到 offer，也决定了你所拿到的 offer 级别。&lt;/p&gt;
&lt;p&gt;对于多数公司，技术面试会有很多轮，且面试官的级别会逐渐提升：从基层员工到部门领导。一般来说，轮数为 2 - 5 轮；如果中途面试失败，而换部门重新开始面试流程，那么轮数可能会叠加至更多。&lt;/p&gt;
&lt;p&gt;由于这一阶段较为复杂，故在此不表，而是在后文更加详细地展开。&lt;/p&gt;
&lt;h3 id=&quot;hr-面试&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#hr-%E9%9D%A2%E8%AF%95&quot; aria-label=&quot;hr 面试 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;HR 面试&lt;/h3&gt;
&lt;p&gt;在通过了所有的技术面试之后，除了少数没有 HR 面试的公司，对于多数公司，最后一轮面试即是 HR 面试。&lt;/p&gt;
&lt;p&gt;不同公司的 HR 面试差别较大。&lt;/p&gt;
&lt;p&gt;许多公司的 HR 面试仅仅用于和候选人沟通一些技术之外的事项，比如对工作地点、薪资的期望，只要不表现得过于出格，这一轮面试不过是走个过场，双方互相沟通，以便发放 offer。因此，这些公司的 HR 面试往往很简截，不会超过半小时，甚至不到十分钟。&lt;/p&gt;
&lt;p&gt;不过，一些公司的 HR 面试比较严肃，不少人折戟于此。在这些公司的 HR 面试中，HR 会从许多角度探查候选人，比如性格习惯、对公司文化价值观的看法等，甚至有些 HR 会显得有些「咄咄逼人」。不过，也不必过于悲观，如果在此面试失败，便说明这家公司确实与你不合，即便顺利通过面试而入职，也大概率是踏入了坑中，日后并不会开心。早点终结对彼此都好。&lt;/p&gt;
&lt;h3 id=&quot;发放-offer&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8F%91%E6%94%BE-offer&quot; aria-label=&quot;发放 offer permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;发放 offer&lt;/h3&gt;
&lt;p&gt;恭喜，你（即将）成功收获一家公司的 offer！&lt;/p&gt;
&lt;p&gt;通常情况下，offer 的发放有两步：先发放录用意向书，然后发放带有薪资的正式 offer。前者可能在面试完不久就发放，后者一般全公司统一发放（比如秋招大概为 10 月份），且需要在一定时间内选择接受或者回绝。&lt;/p&gt;
&lt;p&gt;这一阶段的唯一关键词是：&lt;strong&gt;耐心&lt;/strong&gt;。多数公司在面试流程结束之后，并不会太快给出结果，而是需要等待较长的时间（快则不到一周，慢则可能超过一个月），在此期间，请保持耐心，不要过于焦虑。如果是通过熟人内推，可以定期拜托内推者探听一下消息。&lt;/p&gt;
&lt;p&gt;需要提醒的是，在获得意向书之前，不要轻信任何的口头承诺（譬如你的面试肯定能通过云云），不要因此过早终止其他公司的校招流程。有备无患。&lt;/p&gt;
&lt;p&gt;另一方面，在获得意向书之后，由于其基本上等同于获得了正式 offer，出于道德的考量，请选择性地终止其他公司的流程。比如，你获得了 A 岗位的意向书，同时确定能去 A 岗位就绝对不会去 B 岗位，那么，可以考虑终止 B 岗位的流程，把更多的机会留给他人。收割大量自己不打算接受的 offer 并不是一件有意义的事情。&lt;/p&gt;
&lt;h2 id=&quot;面试指南&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%9D%A2%E8%AF%95%E6%8C%87%E5%8D%97&quot; aria-label=&quot;面试指南 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;面试指南&lt;/h2&gt;
&lt;p&gt;如前所述，技术面试是互联网公司技术岗位校招的核心环节，决定着校招的成败与 offer 的档次，因而在此专门用一个章节来详细展开。&lt;/p&gt;
&lt;p&gt;事先声明，此处没有任何具体公司具体岗位的「面经」（面试经历），我也并不提倡大家通过刷面经来准备面试。事实上，在整个校招过程中，我（几乎）没有看过任何面经。&lt;/p&gt;
&lt;h3 id=&quot;面试前&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%9D%A2%E8%AF%95%E5%89%8D&quot; aria-label=&quot;面试前 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;面试前&lt;/h3&gt;
&lt;p&gt;一个很有趣的问题：「面试前」指的到底是多久之前。&lt;/p&gt;
&lt;p&gt;是等待面试官上线的面试前几分钟吗？是收到下一轮面试通知的面试前几天吗？是投出简历的面试前几个礼拜吗？还是尚未开始校招的面试前几个月？抑或是，初学计算机的面试前几年？&lt;/p&gt;
&lt;p&gt;或许都是，但至少于我而言，后两者才是更加主要的：我并没有在面试前几分钟、前几天、前几个礼拜，做太多特别的准备，而是相当随意地开始一场又一场的面试。&lt;/p&gt;
&lt;p&gt;因此，如何为技术面试做准备，取决于「面试前」的具体指代。&lt;/p&gt;
&lt;h4 id=&quot;前几年&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%89%8D%E5%87%A0%E5%B9%B4&quot; aria-label=&quot;前几年 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;前几年&lt;/h4&gt;
&lt;p&gt;那么，从最实际的角度出发，我的建议是：考一所好大学的计算机专业。&lt;/p&gt;
&lt;p&gt;虽然互联网行业并不迷信学历，但是不得不承认的是，好的学历可以帮助你轻松地越过某些门槛：比如，名校的学生不论简历写的如何，基本上都可以通过简历筛选，至少得到了面试的机会。当然，到了面试环节，学历的作用感知并不强。&lt;/p&gt;
&lt;p&gt;除此之外，更重要的还有两点：&lt;strong&gt;专业课的扎实学习&lt;/strong&gt;与&lt;strong&gt;多写代码的动手能力&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;前者需要认真学习计算机的各门专业课程，比如操作系统、计算机网络、算法与数据结构、计算机体系结构、编译原理等等。当然，需要注意的是，这&lt;strong&gt;不完全等同&lt;/strong&gt;于在这些课程中拿到高分。引用一句 &lt;a href=&quot;https://survivesjtu.gitbook.io/survivesjtumanual/li-zhi-pian/huan-ying-lai-dao-shang-hai-jiao-tong-da-xue&quot;&gt;《交大生存手册》&lt;/a&gt; 的话：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;国内绝部分大学的本科教学，不是濒临崩溃，而是早已崩溃。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;因此，在学校的课业之外，建议通过阅读一些优秀的专业教材，或者追随世界知名大学的公开课，来更加系统、更加科学地学习这些专业领域。而在我的学习过程中，一定程度上参考了 &lt;a href=&quot;https://teachyourselfcs.com/&quot;&gt;TeachYourselfCS&lt;/a&gt; 给出的建议，在此也推荐给大家。&lt;/p&gt;
&lt;p&gt;后者别无他法，只能靠多写代码来实现。或许有些人会认为这句话多余，但是就我的亲身观察来看，计算机专业的一些学生，完全是按照「文科」的方法在学习计算机：背诵各种概念与名词，默写数据结构与算法模板。而在代码量方面，不少人在完成课内的大作业项目（甚至是划水通过的）之余，并不会写更多的代码。我认为，这是不够的。&lt;/p&gt;
&lt;p&gt;在这一方面，我最佩服的为 &lt;a href=&quot;https://github.com/skyzh/&quot;&gt;迟先生&lt;/a&gt;，其代码量与动手能力，超越了几乎 100% 的同龄学生。客观来说，是吾辈楷模。&lt;/p&gt;
&lt;p&gt;另外，还有一点较为「虚无缥缈」：一定程度的「吹牛能力」。并非指不诚信行为，而是指需要具备一定的表达与沟通能力，从而在面试中可以尽量充分展现自我的优秀面。&lt;/p&gt;
&lt;h4 id=&quot;前几个月&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%89%8D%E5%87%A0%E4%B8%AA%E6%9C%88&quot; aria-label=&quot;前几个月 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;前几个月&lt;/h4&gt;
&lt;p&gt;在面试的前几个月，有些人会刷面经来速成前面提到的专业课知识，这样或许有效，但是我并不认同。因为这样只会让面试失去考察的意义，从而恶性发展，让面试的内容不断地往偏难怪的方向畸变，徒增双方的负担。&lt;/p&gt;
&lt;p&gt;如果你在面试的前几年如前所述地积攒了专业知识与代码量，那么，在前几个月，你只需要做一件事：刷题。&lt;/p&gt;
&lt;p&gt;我并不喜欢刷题，但是鉴于目前互联网行业面试的格局，算法题占据了过大的比重，刷题成为了迫不得已但是相当有效的做法。&lt;/p&gt;
&lt;p&gt;如果你有一定的算法竞赛基础，那么此处的刷题只不过是很少量的练习，无非是熟悉一下面试算法题的套路：其难度远低于竞赛算法题，且具备一定的规律；如果你没有算法竞赛的基础，就像我一样，那么，你最好在之前把算法与数据结构课程学的足够好，否则我的建议是先去补习这两门课程，再开始刷题。&lt;/p&gt;
&lt;p&gt;至于刷题本身，这件事并无什么值得讲的。曾经（希望不是现在）作为「做题家」的你我，都很懂得应试教育的那一套。并且 &lt;a href=&quot;https://leetcode.com/&quot;&gt;Leetcode&lt;/a&gt; 平台已经足够成熟，上面有大量的面试算法题，分门别类，难度明确，量力刷一定数量的题目即可（我的体验是，大概两三百道便足够应付绝大多数的面试）。&lt;/p&gt;
&lt;p&gt;当然，不要把刷题当作堆量与死记硬背。&lt;/p&gt;
&lt;h4 id=&quot;前几周--前几天&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%89%8D%E5%87%A0%E5%91%A8--%E5%89%8D%E5%87%A0%E5%A4%A9&quot; aria-label=&quot;前几周  前几天 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;前几周 / 前几天&lt;/h4&gt;
&lt;p&gt;如果你喜欢的话，可以看一下所应聘的公司与岗位的面经，从而对面试的形式与内容有所了解，缓解紧张，并做一些针对性的面试准备。&lt;/p&gt;
&lt;p&gt;不过我啥也没做。&lt;/p&gt;
&lt;h4 id=&quot;前几分钟&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%89%8D%E5%87%A0%E5%88%86%E9%92%9F&quot; aria-label=&quot;前几分钟 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;前几分钟&lt;/h4&gt;
&lt;p&gt;放松点，别太紧张。&lt;/p&gt;
&lt;h3 id=&quot;面试中&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%9D%A2%E8%AF%95%E4%B8%AD&quot; aria-label=&quot;面试中 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;面试中&lt;/h3&gt;
&lt;p&gt;终于来到了正式的面试时间。&lt;/p&gt;
&lt;p&gt;根据我的经历总结，互联网行业的技术岗位校招面试，一般为这些环节的选择性自由组合：自我介绍、校园经历、过往实习、项目经历、专业知识、算法题、系统设计、向面试官提问。&lt;/p&gt;
&lt;p&gt;也即是说，除了一开始的自我介绍和最后的向面试官提问（甚至有些面试这两个也不一定有！），其余环节的顺序和内容均是不确定的，取决于面试官的意愿。&lt;/p&gt;
&lt;p&gt;这些环节，其实没有万能答案，唯一的应对方式是：保持自信，保持沟通，尽量展现自我的优秀面。而如果一定要说的话，每个环节可能有一些需要稍微注意的事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;自我介绍。这一点可以稍做准备，提前想好大概要如何介绍自己，而不至于在面试开场时无话可说。另外，最好同时准备中英文版本的自我介绍。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;校园经历。一般来说，技术面试不会涉及这一点，而是 HR 面试会经常问到。不过，由于我的简历上除了 GPA 便没有其他的校园经历，我并没有过多地被问及，也没有太多的经验可以分享。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;过往实习。在我看来，这一点是简历上除学历外&lt;strong&gt;最重要的内容&lt;/strong&gt;。不论是技术面试还是 HR 面试，这一点是永远避不开的关键环节。在叙述过往实习经历时，需要清晰地呈现实习的岗位与内容，同时由于是校招，也可以讲一些自己实习中的学习与收获（&lt;del&gt;对于混面试时长很有效&lt;/del&gt;）。而如果是技术面试，很大可能面试官还会对实习经历的一些技术细节进一步询问，所以不要编造或夸大经历，以确保自己能够回答出面试官的深入追问，否则会制造出一种「实习没有含金量」的不好印象，适得其反。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;项目经历。如果没有实习经历，或者实习经历不够多，那么，项目经历也是很重要的一环。这里所说的项目经历，对于校招学生来说，往往是某门课程的大作业，或者 Github 上的个人项目。考察的形式和实习经历类似，但是重点会更加放在技术方面。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;专业知识。以问答的形式，面试官会提出某个专业课的问题，譬如老生常谈的「TCP 的三次握手过程如何」，「什么是操作系统的虚拟内存」，「Python 的 GIL 是什么」等等，有相对固定的答案，但是回答的形式很自由，可以按照个人的理解来回答。事实上，在我看来，背面经的模板式回答并不是最佳选项，在确保正确性的前提下，用自己语言梳理一遍，讲出不落俗套的个人理解，才是最完美的回答。关于这一点，推荐一位同学写的文章：&lt;a href=&quot;https://ipotato.me/article/66&quot;&gt;如何在面试中筛选/不做一个「背题家」&lt;/a&gt;，我相当赞同其文的观点。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;算法题。在技术面试，尤其是前几轮的技术面试，现场做算法题往往是无可避免的。做算法题的最大挑战在于其宽泛的提问空间，尽管有如前所述的刷题，但是依旧要做好遇到陌生题目的准备。我就曾多次遇到一时没有思路的题目。而解决方法是，与面试官充分地沟通，即便暂时没有想出最佳的算法，也可以和面试官积极交流想法，从而获得一些提示与建议（这并不丢人！），打开思路。如果实在没有思路，可以先试着写出最简单粗暴的算法，至少证明「你会写代码」，而不要心态崩溃留下一个空白的页面。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;系统设计。一般来说，系统设计题目是对算法题的代替，出现于技术面试的后几轮（面试官为部门领导）。我所遇到的系统设计题不多，而且也没有固定的答案，应当是言之有理即可。其实系统设计一般是社招的考察内容，校招中较为罕见，也要求不高，所以不必太担心。另外，据我猜测，我之所以会遇到系统设计题目，大概率是因为我应聘的岗位是「后端开发」，对于其他岗位，应当是不太可能遇到的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;向面试官提问。这一环节对你的面试表现没有太大影响，但是对于你将来的 offer 选择十分重要。毕竟，面试是一个双向的互动行为，不完全是单向的考核。能够从面试官，将来的同事，口中了解到一些网络上难以搜寻到的部门与岗位信息，我个人觉得是十分有意义的。在这一环节，我常用的问题有：「能否按时间线介绍一下你一天的工作内容呢？」，「部门的工作流程大致是怎样的呢？」等等。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后，我想表达的是，面试本身其实并无太多技巧：只需要将你的能力充分展示即可。如果你在面试前做足了准备，则完全不需要担心面试的发挥。&lt;strong&gt;保持自信，保持沟通，尽管面试本身存在一定的偶然性，但是优秀是掩藏不住的。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;面试后&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%9D%A2%E8%AF%95%E5%90%8E&quot; aria-label=&quot;面试后 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;面试后&lt;/h3&gt;
&lt;p&gt;如果这是一场顺利且愉快的面试，那么，你什么也不用做，开心地等待下一场面试就足够了。&lt;/p&gt;
&lt;p&gt;如果这场面试不太顺利，比如，遇到了没做出来的算法题、没回答上来的专业问题等，那么你可以回顾检查一下这些问题，查漏补缺。毕竟，考虑到面试的重复与套路，大概率这些问题会被再次问到，但愿下一次不要在同一个地方受挫。&lt;/p&gt;
&lt;p&gt;但不管怎样，保持自信，保持乐观，要知道，面试是一件带有偶然性的事情，而且有些面试官其实并不懂得如何面试。&lt;/p&gt;
&lt;h2 id=&quot;拓展阅读&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%8B%93%E5%B1%95%E9%98%85%E8%AF%BB&quot; aria-label=&quot;拓展阅读 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;拓展阅读&lt;/h2&gt;
&lt;p&gt;最后，在准备校招的前前后后，我曾浏览过许多有价值的文档，在此将其列出（部分文档在正文中已提及），以供参阅。同时，也感谢作者们的无私分享：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mindhacks.cn/2011/11/04/how-to-interview-a-person-for-two-years/&quot;&gt;怎样花两年时间去面试一个人 – 刘未鹏 | Mind Hacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zhihu.com/question/39238915&quot;&gt;Google、Facebook 等美国 IT 名企在面试中最看重什么？ - 知乎&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ipotato.me/article/66&quot;&gt;iPotato | 如何在面试中筛选/不做一个「背题家」&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://survivesjtu.gitbook.io/survivesjtumanual/&quot;&gt;上海交通大学生存手册&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://teachyourselfcs.com/&quot;&gt;Teach Yourself Computer Science&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;行文至此，其实作为一名普通的应届生，我不过是参加了比较多的校招面试，加上比较好的运气，对于「校招面试指南」这样的题目，尽管加上了「不完全」，依旧觉得力有未逮。&lt;/p&gt;
&lt;p&gt;这份指南必然不是全面的、权威的、绝对正确的，其间不免有许多我的偏见与无知。&lt;/p&gt;
&lt;p&gt;所以，欢迎大家的评论指正。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[初学前端，制作一个 Gatsby 静态博客]]></title><description><![CDATA[几乎没有任何前端基础的我，如何在一个月内入门「现代化」前端，并使用 Gatsby 制作一个静态博客？]]></description><link>https://www.zackwu.com/posts/2020-09-28-play-with-frontend/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2020-09-28-play-with-frontend/</guid><pubDate>Mon, 28 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;背景&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%83%8C%E6%99%AF&quot; aria-label=&quot;背景 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;背景&lt;/h2&gt;
&lt;p&gt;大约一个月之前，作为一个几乎没有任何前端基础的小白（仅仅手写过简单的 HTML + CSS 页面），在一直从事的后端开发领域之外，突然对「现代化」前端产生了浓烈的好奇与兴趣：毕竟，我学计算机的初衷是创造美好的事物，总是和命令行打交道，不由得觉得有所欠缺。&lt;/p&gt;
&lt;p&gt;另一方面，虽然靠着魔改现有的 Jekyll 主题，这几年我陆陆续续给我的博客进行了多次改造，但其实我一直有股彻底重写、制作一个完全符合自己审美的博客的冲动。伴着 Ruby 的式微，Jekyll 虽然背靠 Github，但在近年迭出的静态博客框架（如 Hugo、Hexo、Gatsby 等）中，也不免有些陈旧过时，这更是让我萌生了用新的框架制作博客的想法。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/frontend-flag.webp&quot; alt=&quot;一个月前的推文&quot;&gt;&lt;/p&gt;
&lt;p&gt;而在近一个月的知识学习与代码编写之后，我成功用上了全新的个人博客，也对现代化前端有了一定的认识，所以写这篇文章，作为记录。&lt;/p&gt;
&lt;h2 id=&quot;前端入门&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%89%8D%E7%AB%AF%E5%85%A5%E9%97%A8&quot; aria-label=&quot;前端入门 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;前端入门&lt;/h2&gt;
&lt;p&gt;在开始制作博客之前，不论选用何种框架与技术，首先需要学习基本的前端知识。&lt;/p&gt;
&lt;p&gt;在请教了一些前端开发者之后，结合我的实际需求，我大致的学习路径如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;HTML 与 CSS&lt;/li&gt;
&lt;li&gt;布局与设计&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;其他现代化前端概念&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;其中多数内容的学习是在 &lt;a href=&quot;https://www.freecodecamp.org/&quot;&gt;freeCodeCamp&lt;/a&gt; 完成。该网站上的课程免费开放，且每一小节均带有在线的交互式练习，学习过程中具有明确的即时反馈，在此我强烈推荐给想要学习前端的同学。&lt;/p&gt;
&lt;h3 id=&quot;html-与-css&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#html-%E4%B8%8E-css&quot; aria-label=&quot;html 与 css permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;HTML 与 CSS&lt;/h3&gt;
&lt;p&gt;由于在之前的项目中，我写过一些简单的传统前端，这一部分对我来说没有太大的困难。&lt;/p&gt;
&lt;p&gt;跟随着 freeCodeCamp 的课程，我快速地过了一遍常用的 HTML 标签与一些新的语义化标签，并对 accessibility 有了一定的认知。（不要写出无脑嵌套 &lt;code class=&quot;language-text&quot;&gt;div&lt;/code&gt; 的网页！）&lt;/p&gt;
&lt;p&gt;而关于 CSS，最大的困难在于如何给网页布局，这曾经是让我感到无比困扰的难题，所幸随着前端的发展，有了灵活好用的 &lt;code class=&quot;language-text&quot;&gt;flex&lt;/code&gt; 和 &lt;code class=&quot;language-text&quot;&gt;grid&lt;/code&gt; 布局，学习这些新的 CSS 布局方式，让我有一种如释重负的感觉。&lt;/p&gt;
&lt;h3 id=&quot;布局与设计&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%B8%83%E5%B1%80%E4%B8%8E%E8%AE%BE%E8%AE%A1&quot; aria-label=&quot;布局与设计 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;布局与设计&lt;/h3&gt;
&lt;p&gt;其实，这一点更多是审美和艺术，而非前端技术。&lt;/p&gt;
&lt;p&gt;作为一个未曾学习过 UI 设计的开发者，我对如何设计出优雅美观的页面尚无太多想法，只有一些朦胧的感受：比如色彩要协调、排版要对齐、风格要统一等。此外，在上面提到的 freeCodeCamp 课程中，对此有一些简单的论述，提到了一些基本的设计原则。&lt;/p&gt;
&lt;p&gt;作为一个快速的解决方案，我选择向优秀的设计学习。在这一个月，我刻意观察了一些美观舒适的页面，既留心他们的配色、排版等设计，也研究他们的布局实现方式。而在我最终完成的博客中，也一定程度借鉴了其他人的设计。&lt;/p&gt;
&lt;h3 id=&quot;react&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#react&quot; aria-label=&quot;react permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;React&lt;/h3&gt;
&lt;p&gt;前端框架之争，我入门之前就有所耳闻。在此我选择了 React 而非 Vue，原因主要在于我的项目没有历史包袱，完全是从零实现，加上 Gatsby 静态博客的绑定。&lt;/p&gt;
&lt;p&gt;React 很复杂，但是我的任务并不复杂：静态博客几乎不涉及状态管理，所以我只学习了十分基础的 React，便足以完成开发。&lt;/p&gt;
&lt;h3 id=&quot;其他现代化前端概念&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%85%B6%E4%BB%96%E7%8E%B0%E4%BB%A3%E5%8C%96%E5%89%8D%E7%AB%AF%E6%A6%82%E5%BF%B5&quot; aria-label=&quot;其他现代化前端概念 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;其他现代化前端概念&lt;/h3&gt;
&lt;p&gt;比起传统的 HTML，CSS，JavaScript 三件套，现代化前端有层出不穷的新奇框架与工具，作为一个初学者，其中有一些我觉得十分有趣且实用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;SCSS/Sass：对 CSS 做出了许多有用且符合直觉的拓展，譬如嵌套的样式定义。我并没有特地去学习，而是在掌握基本的 CSS 之后，凭借直觉和搜索引擎开始编写 SCSS，其间没有遇到太大的障碍。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Styled Components：比起传统的全局样式，在 React 中，直接编写组件级别的样式更为简单快捷，同时也能减少不同组件之间的样式干扰。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Node.js 与 NPM：通过 NPM，前端项目也具有了包管理，能够方便地添加和移除依赖，让后端开发的我感到十分舒适。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;……&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;博客编写&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8D%9A%E5%AE%A2%E7%BC%96%E5%86%99&quot; aria-label=&quot;博客编写 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;博客编写&lt;/h2&gt;
&lt;h3 id=&quot;为什么是-gatsby&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF-gatsby&quot; aria-label=&quot;为什么是 gatsby permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;为什么是 Gatsby&lt;/h3&gt;
&lt;p&gt;回到最初的静态博客框架技术选型。经过调研，目前比较流行的 &lt;a href=&quot;https://github.com/topics/static-site-generator&quot;&gt;静态网站生成器（static site generator）&lt;/a&gt; （按照其 Github 项目的 star 数排序）有：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Next.js：功能强大且用途丰富的 React 框架，但并非专门的静态网站生成器，故排除&lt;/li&gt;
&lt;li&gt;Gatsby：基于 React，具有完备的插件生态系统，被 &lt;a href=&quot;https://reactjs.org/&quot;&gt;React 官网&lt;/a&gt; 所使用&lt;/li&gt;
&lt;li&gt;Hugo：Go 语言编写，高性能，适用于大型静态网站，使用广泛，如 &lt;a href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes 官网&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Jekyll：Ruby 语言编写，Github Page 对其有着很好的支持，但是近年来流行度有所下降&lt;/li&gt;
&lt;li&gt;Hexo：Node.js 语言编写，比较流行&lt;/li&gt;
&lt;li&gt;Vuepress：基于 Vue，流行程度不如上述框架，故排除&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果从实用角度出发，我想我的选择是 Hugo，足够强大，足够流行，并且我对 Go 语言足够熟悉，能够快速地上手；然而 Hugo 的缺点在于「不够前端」，整体设计上看，比较偏向使用传统的前端写法（HTML 模板加上全局 CSS），没有用到现代化前端的强大功能。&lt;/p&gt;
&lt;p&gt;因此，考虑到除了完成开发之外，我还希望能够学习现代化的前端开发，最终的选择便是 Gatsby：根植于前端生态（仿照 cloud native 的说法，或许是 modern frontend native？），流行而强大。&lt;/p&gt;
&lt;p&gt;另一方面，根据 &lt;a href=&quot;https://www.wappalyzer.com/technologies/static-site-generator/&quot;&gt;Wappalyzer 的数据&lt;/a&gt;，Gatsby 确实是近年来最为流行的选择：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/static-site-generator-market-share-wappalyzer.webp&quot; alt=&quot;Static site generator market share&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;如何写一个-gatsby-项目&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%A6%82%E4%BD%95%E5%86%99%E4%B8%80%E4%B8%AA-gatsby-%E9%A1%B9%E7%9B%AE&quot; aria-label=&quot;如何写一个 gatsby 项目 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;如何写一个 Gatsby 项目&lt;/h3&gt;
&lt;p&gt;在此，我无意复述那些 Gatsby 文档中已有的内容，而是仅列出我所用到的一些有用资源。&lt;/p&gt;
&lt;p&gt;如果想要从零开始学习了解 Gatsby，我自己采用并推荐的方式是快速过一遍 &lt;a href=&quot;https://www.gatsbyjs.com/tutorial/&quot;&gt;Gatsby.js Tutorials&lt;/a&gt;，便能基本了解 Gatsby 项目的结构与原理（一点都不复杂）；如果有比较好的前端基础，也可以直接浏览其官方的 &lt;a href=&quot;https://github.com/gatsbyjs/gatsby-starter-blog&quot;&gt;Blog Starter&lt;/a&gt; 代码，获得直观的认识。&lt;/p&gt;
&lt;p&gt;然后再对照某个实际的 Gatsby 项目，比如 &lt;a href=&quot;https://github.com/alxshelepenok/gatsby-starter-lumen&quot;&gt;Gatsby Starter Lumen&lt;/a&gt;，学习许多实用的细节与技巧；当然，这一步也可以按需进行，比如在不太确定某个做法的最佳实践时，参考这些成熟项目的做法（我正是这么做的）。&lt;/p&gt;
&lt;p&gt;除此之外，Gatsby 最为人称道之处在于其完善的 &lt;a href=&quot;https://www.gatsbyjs.com/plugins/&quot;&gt;插件系统&lt;/a&gt;：当你需要实现某个功能时，大概率已经有某个（甚至多个）插件能够帮你做到这件事，那么最好不要自己重复造轮子。事实上，一个 Gatsby 项目的 &lt;code class=&quot;language-text&quot;&gt;gatsby-config.js&lt;/code&gt; 往往会导入许多有用的插件，比如 RSS Feed、sitemap、SEO 插件等等，既节省了编写代码的负担，也保持了很好的模块化与可配置性。不过值得一提的是，并不是所有插件都有较高的质量，特别是同一个功能有多个插件时，最好还是认真仔细地对比并试用一下，比如 webfont 相关插件。&lt;/p&gt;
&lt;h3 id=&quot;我的-gatsby-博客&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%88%91%E7%9A%84-gatsby-%E5%8D%9A%E5%AE%A2&quot; aria-label=&quot;我的 gatsby 博客 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;我的 Gatsby 博客&lt;/h3&gt;
&lt;p&gt;回到博客本身。&lt;/p&gt;
&lt;p&gt;在开始实现之前，我列出了我所期望具有的功能与设计特点。而这些功能基本上最终都得到了实现：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-rebuild-trello.webp&quot; alt=&quot;Trello 看板&quot;&gt;&lt;/p&gt;
&lt;p&gt;如前所述，在编写我的 Gatsby 博客时，我借鉴了许多优秀博客的设计，样式上有所参照。不过由于其他博客的实现是传统的 HTML 模板 + 全局 CSS，而我使用 Gatsby + SCSS + Styled Components，我重新写了大部分代码，以遵循 Gatsby 的最佳实践。大致的源码结构如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ tree src &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
src
├── components
│   ├── gitalk
│   ├── layout
│   │   └── seo
│   ├── main
│   ├── page
│   ├── pagination
│   ├── post
│   ├── postlist
│   ├── sidebar
│   │   ├── copyright
│   │   ├── menu
│   │   ├── sitemeta
│   │   ├── social-links
│   │   └── toc
│   └── tags
├── pages
├── scss
│   └── base
└── templates&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;而在具体的编码实现过程中，也曾遇到过许多细枝末节的问题，不过并无太多展开叙述的意义，在此不表。&lt;/p&gt;
&lt;p&gt;如有兴趣，完整的代码可见 &lt;a href=&quot;https://github.com/izackwu/gatsby-starter-breeze&quot;&gt;izackwu/gatsby-starter-breeze&lt;/a&gt;，以及 &lt;a href=&quot;https://gatsby-starter-breeze.netlify.app/&quot;&gt;在线 Demo&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&quot;最后&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9C%80%E5%90%8E&quot; aria-label=&quot;最后 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;最后&lt;/h2&gt;
&lt;p&gt;当你看到这篇文章时，我的博客已经换上了刚完成的 Gatsby 博客主题，焕然一新。&lt;/p&gt;
&lt;p&gt;而于我而言，通过给自己的博客从头写一个新的 Gatsby 主题，我入门了现代化的前端开发，期间感觉充实而快乐。&lt;/p&gt;
&lt;p&gt;如果你也有一定的空闲时间与精力，那么我推荐你也试着开始探索前端的世界，并创造出自己喜欢的东西。不一定要深入探究前端的高深技术，仅仅用前端的皮毛自娱自乐，就能收获足够多的乐趣。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[我为什么放弃保研，选择直接工作]]></title><description><![CDATA[放弃保研的资格，选择在毕业后直接工作，是一个不同寻常的决定。那么，为什么我会做出这样的决定呢？又有哪些思考呢？]]></description><link>https://www.zackwu.com/posts/2020-07-19-why-i-choose-to-work-after-graduation/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2020-07-19-why-i-choose-to-work-after-graduation/</guid><pubDate>Sun, 19 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;前言&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%89%8D%E8%A8%80&quot; aria-label=&quot;前言 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;前言&lt;/h2&gt;
&lt;p&gt;我是一个习惯于早做规划与反复思索的人。&lt;/p&gt;
&lt;p&gt;而坚持写博客最大的好处就是，可以时不时翻看之前写的文章，宛若跨越时间的荆棘，与曾经的自己促膝长谈。&lt;/p&gt;
&lt;p&gt;回看我在大二那年，十九岁生日当天写下的文章，&lt;a href=&quot;/say-no-to-being-mediocre-at-nineteen/&quot;&gt;十九岁，我不愿让一切走向庸俗&lt;/a&gt;，那时的我写道：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;前路漫漫，迷雾中有无数条通向远方的路，但我永远可以选择自己的方向。所谓学术与科研，或许是许多人推崇之道，但我始终持着怀疑的态度，怀疑这条路是否与我不搭；所谓出国与进修，如果没有目标，单纯地为了出国而出国，又意义何在？或者有着高远的目标，又是否愿意在失败之际委屈将就？所谓毕业后就职，似乎更加直截地宣告了平庸生活的加速到来…… 现在的我，或许还没有自己的答案，但我始终保留着选择的权利，暂时不做选择亦是一种选择。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;出国、保研、就业，三条通向远方的路。何去何从，这样的纠结很早之前就已经缠绕着我，让我时不时感到困顿与惘然。&lt;/p&gt;
&lt;p&gt;而在我大三那年，二十岁生日那天写下的文章，&lt;a href=&quot;/just-move-on/&quot;&gt;二十岁，何妨吟啸且徐行&lt;/a&gt;，这样的纠结，随着我不断努力的观察与思考，并未淡化，反而愈加如浓雾般抹不开：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;现在想来，十九岁时，我的迷惘归结下来，即是对将来自己的出路无所适从：出国留学，国内升学，抑或是早日进入职场。这几条路上，都有前人留下的无数足迹与丰碑，但也无可避免地悬着前人用泪水濯洗的种种失败警示牌。我曾尝试从中选出最优解，然而反复的纠结过后，我所意识到的，是这种比较的注定无结果：每当我觉得某个选择优于其他选择时，总会有某些信息刷新我的认知，让我匆忙撤回自己的决定。一如盲人同时摸象与鲸鱼，用片面的认知去比较复杂的事物，注定失败。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;不过，随着体验的不断丰富，校内实验室的「科研经历」也好，企业的实习经历也罢，来自不同渠道的信息渐渐丰富我对「大象与鲸鱼」的认知，让这三条路的形象渐渐具象而清晰。&lt;/p&gt;
&lt;p&gt;而此时此刻，在我放弃了保研，选择了就业之后，或许是时候给这一切画下总结的句点。&lt;/p&gt;
&lt;h2 id=&quot;我的选择&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%88%91%E7%9A%84%E9%80%89%E6%8B%A9&quot; aria-label=&quot;我的选择 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;我的选择&lt;/h2&gt;
&lt;p&gt;如前所述，在长达好几年的观察与思考之后，我最终做出了放弃保研与出国，选择直接就业的决定。&lt;/p&gt;
&lt;p&gt;那么，为什么？&lt;/p&gt;
&lt;p&gt;先是出国。关于这个选项，我曾仔细考虑，然而最终出于经济上的原因（赴美读硕开销实在过于昂贵）和人生规划的原因（我对学术无甚兴趣，不愿耗费多年去追求博士学位），出国成为了三者中第一个被排除的选项。而站在当下（2020 年）来看，全球疫情的扩散与民族主义情绪的对立，出国虽然依旧有着不可抗拒的诱惑力（比如优渥的学术环境与工作环境），但是更显得充满了极度未知的不确定性。&lt;/p&gt;
&lt;p&gt;我喜欢探索，但不是一个冒险主义者，因而不选择出国。&lt;/p&gt;
&lt;p&gt;而关于在国内读研与直接工作，两者便不那么容易抉择了。如果要总结的话，我放弃保研的原因大概有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;国内读研环境的恶劣&lt;/li&gt;
&lt;li&gt;我对科研没兴趣，但是国内读研不得不涉足学术&lt;/li&gt;
&lt;li&gt;读研的收获不足以覆盖时间成本&lt;/li&gt;
&lt;li&gt;我本科的学校与专业已经足够好&lt;/li&gt;
&lt;li&gt;以我目前的能力，已经能找到比较好的工作&lt;/li&gt;
&lt;li&gt;我厌倦了校园环境，想探索不一样的环境&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当然，在实际做出选择的过程中，所考虑的远不止这些（不然也不至于困扰我这么久），上面列出的，不过是一部分考虑。&lt;/p&gt;
&lt;p&gt;我很清楚，这个选择并不寻常，甚至与多数身边同学的选择完全相反。本科毕业后直接工作，是一条少有人（指和我相似背景的人）选择的路：多数人往往选择出国与读研。&lt;/p&gt;
&lt;p&gt;自然，不同人会对我的选择与原因有不同的看法。不过事实上，这篇文章的目的也不是劝服别人做出和我一样的选择。&lt;/p&gt;
&lt;p&gt;我的选择对于别人并不重要，而值得分享的，是我在做出选择过程中的一些思考与观点。&lt;/p&gt;
&lt;h2 id=&quot;一些思考&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%B8%80%E4%BA%9B%E6%80%9D%E8%80%83&quot; aria-label=&quot;一些思考 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;一些思考&lt;/h2&gt;
&lt;h3 id=&quot;国内读研到底有什么收益&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%9B%BD%E5%86%85%E8%AF%BB%E7%A0%94%E5%88%B0%E5%BA%95%E6%9C%89%E4%BB%80%E4%B9%88%E6%94%B6%E7%9B%8A&quot; aria-label=&quot;国内读研到底有什么收益 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;国内读研到底有什么收益&lt;/h3&gt;
&lt;p&gt;作为一个志不在学术与科研的普通人，所谓读研，其实最终目的还是为了找一份好的工作。&lt;/p&gt;
&lt;p&gt;从这个维度出发，国内的研究生（研究生一般特指硕士）其实是一种混杂的产物：既要参与一定程度的科研，也要努力面向就业市场。而参照常规的研究生经历，两到三年的时间：前一年时间主要用来上课，最后一年往往奔波于实习与找工作，剩余时间在导师的要求下会参与到实验室的一些工作中，并致力于发出论文以达到毕业要求。&lt;/p&gt;
&lt;p&gt;那么，在这个过程中，到底收获了什么呢？入门级别的科研能力（有些人甚至永远不会再用到）？一定的业界实习经验？以及虚无缥缈的思维方式转变与能力锻炼？又或者得到镀金的学历提升？&lt;/p&gt;
&lt;p&gt;或许都有，但可以肯定的是，都不会太多。&lt;/p&gt;
&lt;p&gt;尤其对于我而言，本科的学校与专业已然足够好，且自认为已经拥有了一定的能力，我十分怀疑，倘若我去读研究生，真的会有太多的&lt;strong&gt;有用的收获&lt;/strong&gt;吗？&lt;/p&gt;
&lt;h3 id=&quot;选择合适的道路最重要&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%80%89%E6%8B%A9%E5%90%88%E9%80%82%E7%9A%84%E9%81%93%E8%B7%AF%E6%9C%80%E9%87%8D%E8%A6%81&quot; aria-label=&quot;选择合适的道路最重要 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;选择合适的道路最重要&lt;/h3&gt;
&lt;p&gt;从众心理是很普遍的。&lt;/p&gt;
&lt;p&gt;当你身边几乎所有的人，要么为了出国而费心，要么为了保研而争斗，要么为了考研而努力，十分自然地，你会倾向于加入他们，选择一条人声鼎沸的道路。&lt;/p&gt;
&lt;p&gt;但是，每个人的情况和追求不尽相同，因而每个人最合适的道路也未必相同。&lt;/p&gt;
&lt;p&gt;「选择比努力更重要。」这句话近年来已经广为人知，不少人以此自我调侃，感叹自己当初选择的失误（比如选错学校、选错专业），但当下一次选择到来时，却又不假思索地下意识地站到了主流的人群中，甚至拼尽全力挤出一条道路以加入主流人群。&lt;/p&gt;
&lt;p&gt;诚然，作为一个才识普通的人，我或许不具备选择&lt;strong&gt;最合适&lt;/strong&gt;的道路的能力，但我所希望的，是不盲从、不追随，依靠自身的观察与思考，尽量选出一条&lt;strong&gt;相对合适&lt;/strong&gt;的道路。&lt;/p&gt;
&lt;p&gt;不过话说回来，选择人最多的道路或许不是最优的，但大概率不会是最差的。正如投资理财时直接购买宽基指数（比如沪深 300 指数），虽然没法获得超额收益，但却可以确保自己始终跟上市场，获取市场的平均收益，完全有机会胜过一些「股神」的精挑细选。&lt;/p&gt;
&lt;p&gt;因此，此处并非批评那些做出寻常选择的同学，给自我贴金。而是说，每个人都有适合自己的道路。&lt;/p&gt;
&lt;h3 id=&quot;门槛不等于价值&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%97%A8%E6%A7%9B%E4%B8%8D%E7%AD%89%E4%BA%8E%E4%BB%B7%E5%80%BC&quot; aria-label=&quot;门槛不等于价值 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;门槛不等于价值&lt;/h3&gt;
&lt;p&gt;或许是思维惯性使然，从小就生活在竞争中的我们，往往会认为，门槛等于价值。就比如，难考的学校一定比容易考的学校好，录取分数高的专业一定比分数低的专业有前途，难啃的骨头一定好吃（不过话说回来，炖骨头真的挺好吃的）。&lt;/p&gt;
&lt;p&gt;因此，由于考研的激烈竞争，保研对成绩的高门槛，许多人会自然而然地认为，读研是一件很棒的事情。一些人在没有仔细思索的前提下，就认定这是一条光明的道路，甚至为此奋力竞争（学校每年都会因为保研闹出不少事情，让人啼笑皆非）。&lt;/p&gt;
&lt;p&gt;对我而言，我的成绩（前 10 %）应该足以让我轻松从容地进行保研，是不少考研党所羡慕万分的资本。&lt;/p&gt;
&lt;p&gt;然而，有资格保研，有资格跨过高门槛，不代表着跨过门槛就是最佳的选择。&lt;/p&gt;
&lt;p&gt;事实上，我渐渐意识到，拥有跨过门槛的能力（譬如有比较高的 GPA）仅仅意味着拥有比常人稍多的选项，并不意味着就一定要跨过门槛。这是一种宝贵的自由，是选择的权利，而不应该据此自我认定一些必选项，自我束缚，反倒失去了自由。&lt;/p&gt;
&lt;p&gt;另一方面，如前所述，国内读研虽然是一件门槛比较高的事情，但是其价值与收益，在我看来与其门槛的高度并不一定相衬。&lt;/p&gt;
&lt;h3 id=&quot;不可忽视的时间成本&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%B8%8D%E5%8F%AF%E5%BF%BD%E8%A7%86%E7%9A%84%E6%97%B6%E9%97%B4%E6%88%90%E6%9C%AC&quot; aria-label=&quot;不可忽视的时间成本 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;不可忽视的时间成本&lt;/h3&gt;
&lt;p&gt;在我做决定的过程中，最常见到的观点大抵如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;其他条件差不多时，研究生学历肯定比本科学历好，研究生找工作肯定比本科生容易。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这没有错。&lt;/p&gt;
&lt;p&gt;但是在我看来，这忽视了一个很重要的因素：为了获得研究生学历，所付出的时间成本与性价比。&lt;/p&gt;
&lt;p&gt;举一个例子，如果高考复读 10 年，可以 100% 保证提升 10 分 的高考分数，有多少人会愿意呢？高考分数多得 10 分，这自然是一件绝佳的事情，但是如果代价是复读 10 年的光阴，想必多数人都会认为这是一笔不划算的交易吧？&lt;/p&gt;
&lt;p&gt;同样的，研究生学历固然好，但是其代价是两到三年的时间（且不论其间涉及的精力），可以说是一笔不小的时间成本了。相同的时间，对于一个本科毕业后就进入业界工作的同学，或许，他会通过实际的工程与业务，得到更多的经验，提升更多的能力？&lt;/p&gt;
&lt;p&gt;而至于找工作，同样的条件下，研究生确实比本科生有优势。但时间并不是静止的，研究生的比较对象，应当是工作了三年的本科生，这样孰优孰劣呢？&lt;/p&gt;
&lt;h2 id=&quot;拓展阅读&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%8B%93%E5%B1%95%E9%98%85%E8%AF%BB&quot; aria-label=&quot;拓展阅读 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;拓展阅读&lt;/h2&gt;
&lt;p&gt;人类的悲欢并不相通，但是相似。&lt;/p&gt;
&lt;p&gt;关于读研与工作，面临同样困扰的也并非只有我一个人。&lt;/p&gt;
&lt;p&gt;在做出决定的过程中，我阅读了不少人的博客与帖子，从中获得了一些宝贵的信息与经验，或多或少地影响了我最终的决定。&lt;/p&gt;
&lt;p&gt;由于之前并未刻意保存浏览过的网页，在此，仅仅列出其中的一小部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://laike9m.com/blog/suo-yi-dao-di-yao-bu-yao-du-yan,119/&quot;&gt;所以，到底要不要读研？ - laike9m’s blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gaocegege.com/Blog/%E9%9A%8F%E7%AC%94/master&quot;&gt;研究生复盘 | 高策&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ipotato.me/article/65&quot;&gt;iPotato | 在读研 &amp;#x26; 工作中选择后者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.v2ex.com/t/580275&quot;&gt;已有名校 CS 本科学历，读研对于计算机行业的职业发展有多大的意义？ - V2EX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在这里，感谢互联网的开放与共享精神，感谢每一位无私分享经验的陌生人。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[《构建之法》与微软实习面试]]></title><description><![CDATA[不久之前，参加了微软实习的面试，当时觉得面试经历颇为不可思议；在读过《构建之法》之后，却似乎慢慢领会其中深意。]]></description><link>https://www.zackwu.com/posts/2020-06-22-build-to-win/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2020-06-22-build-to-win/</guid><pubDate>Mon, 22 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;前言&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%89%8D%E8%A8%80&quot; aria-label=&quot;前言 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;前言&lt;/h2&gt;
&lt;p&gt;关于微软实习面试的体验，我其实在上一篇文章 (&lt;a href=&quot;/2020-summer-internship/#%E5%BE%AE%E8%BD%AF%EF%BC%89&quot;&gt;2020 年，我寻找暑期实习的经历与经验 &lt;/a&gt; 中已经有所涉及：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;而最后一轮面试，由部门 leader 进行，形式和前两轮差别不是特别大，不过技术的比重比较低，相当大一部分内容是「谈人生」（即技术之外的价值观与理念）.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;当时对此一带而过，主要出于不愿过多泄露面试细节的考虑，以及自己当时其实对这场面试尚且有些「摸不着头脑」。&lt;/p&gt;
&lt;p&gt;而今旧事重提，完全缘于最近所阅读的 &lt;a href=&quot;https://book.douban.com/subject/27069503/&quot;&gt;《构建之法》&lt;/a&gt;——一本由微软亚洲研究院首席研发经理 &lt;a href=&quot;https://www.linkedin.com/in/xinzou/&quot;&gt;邹欣&lt;/a&gt; 所写的「软件工程」书籍。在阅读这本书之后，感触颇多，联想不久前参加的微软实习面试：当时觉得其中的面试经历颇为不可思议，如今看来，却似乎可以慢慢领会其中深意。&lt;/p&gt;
&lt;p&gt;那么，在这篇文章中，就先&lt;strong&gt;以不透露过多细节的方式&lt;/strong&gt;，尽量较为具体地展开我微软实习的第三轮面试，然后谈谈《构建之法》这本书和我的一些想法。&lt;/p&gt;
&lt;h2 id=&quot;微软实习的第三轮面试&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%BE%AE%E8%BD%AF%E5%AE%9E%E4%B9%A0%E7%9A%84%E7%AC%AC%E4%B8%89%E8%BD%AE%E9%9D%A2%E8%AF%95&quot; aria-label=&quot;微软实习的第三轮面试 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;微软实习的第三轮面试&lt;/h2&gt;
&lt;p&gt;在微软实习的面试中，我所经历的，前两轮是较为常规的技术面试，第三轮是比较特别的部门 leader 面试。如前所述，这一轮面试技术方面的含量比较低，而技术之外的内容占据了绝大部分。&lt;/p&gt;
&lt;p&gt;面试伊始，面试官给了一道&lt;strong&gt;相当简单&lt;/strong&gt;的算法题目：大概只花了 10 分钟不到，我便写出了复杂度上最优的解法。而在我写出解法之后，面试官让我详细解释了每个变量存在的必要性，并反复让我优化代码的写法以提升代码可读性和精简程度。&lt;/p&gt;
&lt;p&gt;至此，仅仅 20 分钟不到。&lt;/p&gt;
&lt;p&gt;然而，让我没想到的是，在整场面试之后的剩余时间，足足 1 个小时有余，我经历了极为不可思议的「灵魂拷问」。围绕着一个核心问题：「这样做就够了吗？什么时候可以确定你任务完成了？」，面试官抛出了一个又一个问题，我则战战兢兢地尝试着做出一个又一个回答。比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如何为这个程序设计测试？&lt;/li&gt;
&lt;li&gt;你所设计的这些测试真的足够了吗？&lt;/li&gt;
&lt;li&gt;对于一个函数，你实现了它，那么怎样可以确保你的任务完成了，什么时候你可以放心地说「我可以下班了」呢？&lt;/li&gt;
&lt;li&gt;测试的本质是什么呢？你测试的目的是什么呢？&lt;/li&gt;
&lt;li&gt;测试的目的是确保程序的预期和实际相符吗？&lt;/li&gt;
&lt;li&gt;有了完美的测试覆盖率，就能确保预期和实际相符吗？&lt;/li&gt;
&lt;li&gt;写程序的目的到底是什么呢？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一切的一切，这些连环「拷问」，在面试临近结束的最后 10 分钟，终于真相大白：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;面试官：你刚才提到了预期，那比预期的程度还要强一点的是？&lt;/li&gt;
&lt;li&gt;我：要求？&lt;/li&gt;
&lt;li&gt;面试官：正确，谁的要求？&lt;/li&gt;
&lt;li&gt;我：客户的要求？&lt;/li&gt;
&lt;li&gt;面试官：完全正确！我们微软之所以能做出比别家更好的软件，成为成功的企业，就是因为我们满足了客户的要求。在很多时候，你写了一个软件，但是并没有搞清楚客户的要求，所以会失败。在微软，其实你要花 99% 的时间去思考，然后才能动手写代码。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;原话不完全如此，但大意如此。&lt;/p&gt;
&lt;p&gt;就我个人的感受而言，当我听到「客户的要求」时，一时觉得十分难以接受，甚至产生了严重的怀疑：问了这么多问题，结果最终的答案居然是这个？这场面试的意义何在？是不是因为我之前的表现，所以这场面试只是走个过场？……&lt;/p&gt;
&lt;p&gt;幸运的是，尽管我在这场面试中表现只能算差强人意，但最终还是成功通过了。然而，这场面试，在之后很长的一段时间困扰着我，直到最近我读了《构建之法》这本书。&lt;/p&gt;
&lt;h2 id=&quot;构建之法与软件工程&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9E%84%E5%BB%BA%E4%B9%8B%E6%B3%95%E4%B8%8E%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B&quot; aria-label=&quot;构建之法与软件工程 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;《构建之法》与软件工程&lt;/h2&gt;
&lt;p&gt;坦白来说，软件工程是我在大学期间唯一的一门没有好好学的计算机专业课程。&lt;/p&gt;
&lt;p&gt;一方面是学校的课程质量低下。学校的这门课开设于大二，所用的教材是 &lt;a href=&quot;https://book.douban.com/subject/5952570/&quot;&gt;《面对对象软件工程》&lt;/a&gt;, 一本厚厚的陈旧的传统教材。而当时的授课老师，上课也不过是复述着书上的各种概念，就连举例子也生搬硬套书上给出的那些明显不符合我国社会环境的例子。一学期听下来，只觉得大而无当，云里雾里，除了让我认识了各种图表和文档，在当时看来觉得几乎毫无收获，因此便划水飘过。&lt;/p&gt;
&lt;p&gt;另一方面是我对软件工程意义的不了解与轻视。当时的我，没有经历过大型项目的开发，也没有真正开发过有商业价值的软件系统，仅仅是写了许多玩具级别的项目，自然是意识不到软件工程的意义。更何况，即便通过学校开设的课程，所做的课程项目，除了应付交差，也完全用不上所学的各种繁复的图表与文档，更是给我留下了对软件工程的不佳印象。&lt;/p&gt;
&lt;p&gt;那么，为什么最近我会主动去阅读《构建之法》来学习软件工程呢？其实很简单，上述两个方面的困顿随着我的学习与成长而渐渐消散了，所以学习软件工程是一件很自然的事情。在实习过程中接触了业界真正创造商业价值的软件系统，在 Github 上参与了较为大型的开源项目，以及学校后续课程项目与他人&lt;strong&gt;真正地协作开发&lt;/strong&gt;（而不是「抱大腿式的小组项目」）的经历，均使得我渐渐意识到：不应该用「手工作坊式」的方法进行开发，而需要学习成熟的开发流程。而《构建之法》这本书，其实在学习软件工程课程时，身边的同学便已经向我推荐过。&lt;/p&gt;
&lt;p&gt;那么，《构建之法》这本书讲了些什么？又好在哪里呢？&lt;/p&gt;
&lt;p&gt;其实一言以概之，《构建之法》这本书以&lt;strong&gt;符合实际&lt;/strong&gt;（包括业界开发的实际和大学软件工程教学的实际）的方式，&lt;strong&gt;有侧重&lt;/strong&gt;地讲解了真正有意义的软件工程实践，而对于传统教材着墨颇多的图表和文档点到辄止，让人能够愉快且带着兴趣地读下去并有所收获。顺便一提，这本书的英文名是 &lt;em&gt;Build to win&lt;/em&gt;，也很好地概括了书的内容。&lt;/p&gt;
&lt;p&gt;在这里我无意摘抄书中的章句，只是简单谈谈我阅读后的收获与体会。&lt;/p&gt;
&lt;h3 id=&quot;三个公式&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%B8%89%E4%B8%AA%E5%85%AC%E5%BC%8F&quot; aria-label=&quot;三个公式 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;三个公式&lt;/h3&gt;
&lt;p&gt;书中让我印象最为深刻的，是三个简单的公式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;程序 = 算法 + 数据结构&lt;/li&gt;
&lt;li&gt;软件 = 程序 + 软件工程&lt;/li&gt;
&lt;li&gt;软件企业 = 软件 + 商业模式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在刚接触计算机时，许多人往往沉醉于第一个公式，学习各种精巧的算法与数据结构，能够用很巧妙的方式写出程序。其实我很佩服这样的人，尤其是在高中阶段便接触 OI 竞赛学习算法的同学，他们的程序设计能力远远超过我。&lt;/p&gt;
&lt;p&gt;而在学习了许多基础概念之后，我便开始了在各种玩具项目中编写代码，这一阶段并不能意识到软件工程的重要性，反而会觉得软件工程碍手碍脚（我都能一个晚上开发出来，还需要写文档设计架构做什么呢？），正如我学习软件工程这门课的时候。而通过接触大型的、商业的软件项目，与越来越多的人协作开发，便会很自然地意识到第二个公式的意义。&lt;/p&gt;
&lt;p&gt;至于第三个公式，却往往被过分强调以贬低第二个公式。作者在书中时不时的提及我国新兴的互联网企业：他们 996 高负荷工作却缺乏成熟的软件工程能力，也能依靠创新的商业模式取得了巨大的成功。（当然，书中也不是全然贬低这些互联网企业，关于敏捷开发，这些企业应当是相当优秀的。）&lt;/p&gt;
&lt;p&gt;回想微软实习的第三轮面试，最终的答案是「客户的需求」，当时或许觉得有些难以理解，现在对照这三个公式，不也合情合理吗？从商业公司（比如微软）的角度去看待，程序设计的终极目的是满足客户的需求，那么对于开发人员，什么时候才能确定自己任务完成呢？自然是客户的需求被满足之后。虽然在面试中这个问题或许不甚妥当（毕竟答案过于唯一且出乎意料），但确实对我有很大的启发，让我开始从不同的角度去审视自己的技能与职业发展，思考实际中工作的意义与价值。&lt;/p&gt;
&lt;p&gt;于我而言，目前的层次是努力接近第二个公式，因而学习软件工程。&lt;/p&gt;
&lt;h3 id=&quot;现代软件工程&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%8E%B0%E4%BB%A3%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B&quot; aria-label=&quot;现代软件工程 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;现代软件工程&lt;/h3&gt;
&lt;p&gt;学校授课所选定的教材，其陈腐的一角，体现在对现代软件工程的敏捷开发毫无介绍，而是采用了传统的瀑布流和文档式开发。而这本书，则介绍了较为符合当下业界实际的各种开发流程。&lt;/p&gt;
&lt;p&gt;作者作为微软（或许在不少人眼中已然陈旧落伍的企业）的员工，其写的内容是对二者的平衡：既保留了传统软件工程的优秀实践，也引进了现代软件工程的敏捷与效率。比如持续集成（CI）与持续交付（CD），现在已经被广泛应用，就连我的 Github 玩具项目也开始使用，而陈腐的教材对此避而不谈；又比如测试驱动开发（TDD）、结对编程等各种开发模式，也是对于软件开发流程的颠覆与创新，赋予了不同开发场景下的多种实践方式。&lt;/p&gt;
&lt;p&gt;事实上，现代软件工程的实践繁多，但这种繁多不同于陈腐教材中文档与图表的繁多。前者是有价值的字典般的繁多，可以根据自身的实际情况合理选择以达到精简干练；后者往往是流程的繁多，为了追求某种「绝对的仪式感」而削足适履创造出的冗杂（当然，需要澄清的是，在特定场合下，这样的繁复流程还是有价值的）。&lt;/p&gt;
&lt;p&gt;书中介绍了许多或时髦或传统的开发模式。模式虽多，我在阅读时大体却只是快速浏览，仅仅关注于那些我已经遇到过对应场景的开发模式，读起来颇有种得心应手的舒畅与事后总结般的灵光一现。&lt;/p&gt;
&lt;h3 id=&quot;测试之道&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%B5%8B%E8%AF%95%E4%B9%8B%E9%81%93&quot; aria-label=&quot;测试之道 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;测试之道&lt;/h3&gt;
&lt;p&gt;什么是测试呢？在传统的软件工程教材中，给出了测试所需的一系列文档和图表，以及分门别类的各种测试类型；而在本书中，作者也给出了多种测试，并且提出了测试的一些要求和规范（不是以文档的形式！）。&lt;/p&gt;
&lt;p&gt;不过有趣的是，书中强调测试人员的重要性，甚至举了某公司裁撤测试人员作为反面例子，然而微软却在前些年大刀阔斧地砍掉了测试团队，让开发人员负责测试。&lt;/p&gt;
&lt;p&gt;那么话说回来，测试到底是为了什么呢？在面试中，我和面试官就此达成了共识：测试是为了确保程序的实际和预期相符，包括功能性和非功能性。而为了达到这个目的，我们有各种各样的测试手段，比如单元测试、集成测试等等。但还是回到终极答案上，我们的终极目的是什么呢？是满足客户的需求，测试不过是满足「我们假想出来的客户需求」。&lt;/p&gt;
&lt;h2 id=&quot;总结&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%80%BB%E7%BB%93&quot; aria-label=&quot;总结 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;总结&lt;/h2&gt;
&lt;p&gt;在即将开始微软的暑期实习之前，飞快地读完《构建之法》之后，回想几个月前的微软面试经历，胡思乱想了很多，所以写了这篇文章。&lt;/p&gt;
&lt;p&gt;其实，作为一个大三学生，我对软件工程的理解还是相当肤浅的：虽然有了一定的开发经历，但不过是浅尝辄止。有没有什么方法可以学习软件工程呢？或许阅读《构建之法》是一个不错的方法，但纸上得来终觉浅，我所缺乏的，是更多的实际开发经历。&lt;/p&gt;
&lt;p&gt;然而不论如何，这一切都只是思考的起点与探索的开始，写出来和大家分享。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[2020 年，我寻找暑期实习的经历与经验]]></title><description><![CDATA[2020 年，大三，按照常规的人生节奏，我踏上了寻找暑期实习的征途。至今，我收到了满意的 offer，回首看来，有哪些经历与经验？]]></description><link>https://www.zackwu.com/posts/2020-04-23-2020-summer-internship/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2020-04-23-2020-summer-internship/</guid><pubDate>Thu, 23 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;概述&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%A6%82%E8%BF%B0&quot; aria-label=&quot;概述 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;概述&lt;/h2&gt;
&lt;p&gt;2020 年，大三，按照常规的人生节奏，我踏上了寻找暑期实习的征途。&lt;/p&gt;
&lt;p&gt;先开门见山一下，在写此文时，我基本结束了寻找暑期实习的历程。总的来说，我一共投递了 5 家公司（谷歌，微软，亚马逊，腾讯，蚂蚁金服），并最终选择了微软。具体情况是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;亚马逊，可能是因为投的太晚了而直接石沉大海，杳无音信&lt;/li&gt;
&lt;li&gt;谷歌，面试进行到一半，突然宣布今年因为疫情取消了国内所有的暑期实习&lt;/li&gt;
&lt;li&gt;腾讯，成功拿到了 WXG 微信事业群，微信支付部门，后台开发的 offer&lt;/li&gt;
&lt;li&gt;蚂蚁金服，顺利拿到了广告技术部门，后台开发的 offer&lt;/li&gt;
&lt;li&gt;微软，顺利拿到了上海 Cloud + AI 部门 SWE 实习 offer&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;经历&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%BB%8F%E5%8E%86&quot; aria-label=&quot;经历 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;经历&lt;/h2&gt;
&lt;p&gt;需要说明的是，在开始寻找暑期实习之前，我已经在字节跳动有过三个月的日常实习经历。由于这段经历并不是特别愉快（具体见 &lt;a href=&quot;/my-internship-at-bytedance/&quot;&gt;我之前的文章&lt;/a&gt;），我对于即将到来的暑期实习，我所期待的，是去体验不同于国内互联网企业的另一种工作与生活方式。&lt;/p&gt;
&lt;p&gt;那么，在寻找暑期实习伊始，我仅仅选定了两家目标公司：谷歌与微软。而可能出于外企较为慵懒的工作效率以及我简历的不够过硬，在我网申投出简历两三个月后，这两家公司依旧毫无进展。自然而然地，在两三个月无果后，为了减少内心的焦虑不安，我稍做准备，额外挑了两家国内互联网企业：腾讯与蚂蚁金服，以期「保底」。因此，总体时间线如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2020-summer-internship-timeline.webp&quot; alt=&quot;Timeline&quot;&gt;&lt;/p&gt;
&lt;p&gt;再逐公司记录一下我寻找实习的经历吧。&lt;/p&gt;
&lt;h3 id=&quot;谷歌&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%B0%B7%E6%AD%8C&quot; aria-label=&quot;谷歌 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;谷歌&lt;/h3&gt;
&lt;p&gt;我最早投递的，即是谷歌。在去年 12 月，谷歌放出今年的暑期实习岗位时，我就立刻网申投递简历（&lt;strong&gt;此处其实犯了一个很严重的错误，后文详述&lt;/strong&gt;）；一个月后，谷歌的招聘人员联系了我，填写了一些诸如期望城市、方便的面试时间等额外信息，等待安排面试。然而，虽然每周五 HR 会给我发一封进度跟进的邮件，但自此长达两个月的面试等待期实在让人难以忍受。&lt;/p&gt;
&lt;p&gt;终于，在三月中旬，漫长的等待后，我迎来了谷歌的第一场电话面试。如网上许多人的描述，谷歌的面试可以说是：开局一个空白的 Google Doc 文档，面试不聊别的，全靠做算法题。于我而言，遇到的面试官很友善，沟通很不错，而且题目难度也不高（两道题，最终都完美做出来了），总体体验比较愉快。因此，第一场面试顺利通过。&lt;/p&gt;
&lt;p&gt;然而不巧的是，就在等待第二场面试时，由于新冠疫情的影响，谷歌取消了今年国内所有的暑期实习，所以我与谷歌也自此暂别。当然，客观来说，从我被安排面试的时间来看，即便没有疫情，大概率也会因为 Team Match 过晚而无法成功拿到谷歌的实习 offer，故坦然处之。&lt;/p&gt;
&lt;h3 id=&quot;微软&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%BE%AE%E8%BD%AF&quot; aria-label=&quot;微软 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;微软&lt;/h3&gt;
&lt;p&gt;紧随谷歌之后，在今年的 1 月，微软放出今年的暑期实习岗位时，我依旧立刻网申投递了简历（&lt;strong&gt;此处所犯错误同上&lt;/strong&gt;）。然而幸运的是，在 2 月末，亡羊补牢，我赶上了微软&lt;strong&gt;内推&lt;/strong&gt;的截止期，由一位学长帮助进行了内推。&lt;/p&gt;
&lt;p&gt;微软的实习面试安排在 3 月底，就我所面试的部门（上海，Cloud + AI）而言，三轮面试安排在了一个下午，相当紧凑。第一轮面试与第二轮面试类似，都是由一位 Individual Contributor 进行技术面试，其中涉及到简历上内容的介绍、计算机基础知识以及常规的算法题，总体难度不大，面试十分友好，体验十分愉快。而最后一轮面试，由部门 leader 进行，形式和前两轮差别不是特别大，不过技术的比重比较低，相当大一部门内容是「谈人生」（即技术之外的价值观与理念）。&lt;/p&gt;
&lt;p&gt;有趣的是，我前两轮的面试官，均为女性工程师（大概是我今年寻找暑期实习过程中所遇到的，仅有的二位女性工程师）；而第三轮的面试官，似乎是一个中文讲得很好的外国人（不完全确定，通过口音判断），而且还放了我一次鸽子，不过总的来说，微软的三轮面试体验还是相当不错的，没有太大的压力。&lt;/p&gt;
&lt;p&gt;而在面试结束后，大致两周（官方说法）内告知面试结果。根据为数的不多样本，似乎如果面试没有通过，拒信发得很快；而如果面试顺利通过，等待期可能会长达一个月。&lt;/p&gt;
&lt;p&gt;在我的多次邮件催促下，终于熬过漫长的等待，于 4 月中旬，顺利收到了 offer，并选择接受。&lt;/p&gt;
&lt;h3 id=&quot;腾讯&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%85%BE%E8%AE%AF&quot; aria-label=&quot;腾讯 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;腾讯&lt;/h3&gt;
&lt;p&gt;如前所述，腾讯并非我一开始的目标公司，而是在等待的焦虑中为了「保底」而投递。在 3 月中旬，等待谷歌和面试时，我联系到了某位腾讯 HR，由她帮助，内推投递了暑期实习。&lt;/p&gt;
&lt;p&gt;不得不夸赞的是，腾讯（包括后文的蚂蚁金服），&lt;strong&gt;处理实习申请的流程极为迅速&lt;/strong&gt;，短短 20 天内，便完成了「两次面试流程」：第一次面试 TEG 事业群，在两轮面试之后失败告终；第二次面试 WXG 事业群，在三轮面试后成功拿到 offer。&lt;/p&gt;
&lt;p&gt;其实，倘若顺利的话，腾讯实习，应当是只有三轮面试的：前两轮技术面试，第三轮 HR 面试。此外，如果一个部门面试失败，会有机会被其他部门「重新捞起」，从头开始面试流程。&lt;/p&gt;
&lt;p&gt;至于面试经历，我所经历的四轮技术面试，大同小异，无非是询问一些计算机基本知识和简历上内容，而且巧合的是，四轮面试都未遇到算法题。而 HR 面试，主要是沟通一下入职事项，了解个人性格等等，基本上不会在这一轮面试失败。&lt;/p&gt;
&lt;p&gt;值得一谈的是，我在前两轮面试的「作死行为」。第一轮面试，面试官询问我是否参与过开源项目，我答没有，他对此略有不满。在面试的最后，由我提问，我问面试官「贵部门应该是使用了许多开源项目，那么，是否有回馈开源社区？」，面试官一时语塞；第二轮面试，不知为何，聊到工作与生活的平衡，我吐槽 996 工作制的不合理与反人性，面试官沉默不语，而我果不其然地在面试结束后几小时内收到了面试失败的通知。&lt;/p&gt;
&lt;p&gt;以此为戒，在第二次面试流程，即，面试 WXG 的过程，总体比较顺利。有些尴尬的是，HR 面试中，HR 似乎是看到了之前面试官对我的评价，一阵见血地询问「你似乎对 996 很有意见，那你是否愿意加班呢？」一时颇为尴尬，所幸最终无恙，成功拿到了微信支付后台开发的 offer。&lt;/p&gt;
&lt;h3 id=&quot;蚂蚁金服&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%9A%82%E8%9A%81%E9%87%91%E6%9C%8D&quot; aria-label=&quot;蚂蚁金服 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;蚂蚁金服&lt;/h3&gt;
&lt;p&gt;其实，在申请蚂蚁金服的实习之前，一直十分犹豫于其繁复的面试流程。不过事实表明，蚂蚁金服虽然流程繁琐，但是处理效率很高，从投递到 offer，只花了 20 天不到。&lt;/p&gt;
&lt;p&gt;在投递蚂蚁金服之后，首先要做的，是冗长繁琐的行为测试题，包括语文阅读、数学图表阅读、类智力测试题的找规律题以及性格测试题。虽然从结果看，这一部分似乎影响不大，但是实在让人极度不愉快。&lt;/p&gt;
&lt;p&gt;不同于其他公司（比如微软、腾讯），蚂蚁金服即便是内推，也无法免去笔试题目。所谓笔试，是在投递后，自选一场笔试考试时间，在牛客平台，完成两道算法编程题目。我所遇到的笔试题目，难度并不大，因而全部顺利做出。&lt;/p&gt;
&lt;p&gt;在笔试结束后，即开始面试，共有 5 轮：除了最后一轮是 HR 面试，前四轮都是技术面试，不同点在于面试官，分别是普通员工、小 leader、本部门 leader、其他部门 leader。前四轮技术面试，总体上和腾讯的技术面试差不多，包括简历内容、计算机基本知识、算法题以及系统设计题，总体难度不大，不过偶有我回答不出的题目。而最后一轮 HR 面试，据传是有一定概率在此失败的（阿里的 HR 似乎权力比较大？）。&lt;/p&gt;
&lt;p&gt;在面试中，我发现了比较有意思的一个现象：即便是技术面，所遇到的面试官的口才也相当不错，能够就我的提问，滔滔不绝且逻辑清晰地回答十余分钟而无法打断。或许，这是阿里的企业文化所造就？&lt;/p&gt;
&lt;p&gt;面试结束，大约两三天后，收到了部门 leader 的电话，告知已获得 offer，不过需要确认我是否有意向接受，若不打算接受，对方为了节省「宝贵的」名额，就不发放正式的 offer。由于此时我已经正式接受了微软的实习 offer，虽然可以多诳骗一个 offer，但是为了不浪费对方的名额，还是如实告知了我的意向。&lt;/p&gt;
&lt;h2 id=&quot;经验&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%BB%8F%E9%AA%8C&quot; aria-label=&quot;经验 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;经验&lt;/h2&gt;
&lt;p&gt;总的来说，其实我寻找暑期实习的过程还算顺利，虽有些磕绊，但比较幸运，最终还是拿到了不少 offer。&lt;/p&gt;
&lt;p&gt;现在回顾这段经历，其实可以发现，我犯了好几个明显的错误：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;微软和谷歌一开始直接网申，而没有走内推通道&lt;/li&gt;
&lt;li&gt;一开始投的公司过少&lt;/li&gt;
&lt;li&gt;面试中过于言而无忌&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;第 1 点，从我寻找实习的经历来看，内推往往具有极其强大的力量，仅仅靠网申，即便再早投递，处理的优先级也不如内推。倘若我没有亡羊补牢地补上了微软内推，那恐怕至今我离微软 offer 还遥遥无期。所以，在今后的求职中，不论是实习、校招还是社招，尽量让认识的人帮忙内推。&lt;/p&gt;
&lt;p&gt;第 2 点，如果不是特别自信，不要把鸡蛋放在一个篮子里，而应该广撒网。多投几家公司。或许，这并不是真的打算去这些公司，而是为了减轻内心的焦虑与不安。在等待中，倘若手头有保底的选项，即便暂时不是最满意的，也能极大地缓解压力。而且事实上，现在自我评估能力，我想，我的能力还不足以自信到只投一两家公司就能稳拿 offer。毕竟，面试中存在相当大的运气成分，「饱和式」申请方能让自己避免意外。&lt;/p&gt;
&lt;p&gt;第 3 点，面试虽然是双方互相交流，但是毕竟是一个相对正式的沟通，所以应该把握说话的方式与分寸。坦诚固然是不错的品质，但有所保留或许会给自己多留一点余地。&lt;/p&gt;
&lt;p&gt;总结一下，从我寻找暑期实习的经历，我得出的经验可以概括为：内推，广撒网，合理沟通。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[我在字节跳动实习的三个月]]></title><description><![CDATA[在字节跳动短暂的三个月实习，印证并补充了我在实习前对国内互联网行业的所有设想，包括好的方面与坏的方面。]]></description><link>https://www.zackwu.com/posts/2020-01-18-my-internship-at-bytedance/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2020-01-18-my-internship-at-bytedance/</guid><pubDate>Sat, 18 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;本文基于我从字节跳动离职时的申请，略微修改。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在字节跳动短暂的三个月实习，从去年十月顺手投出简历开始，到昨天办完所有的离职手续而结束。其间所经历的，印证并补充了我在实习前对国内互联网行业的所有设想，包括&lt;strong&gt;好的方面&lt;/strong&gt;与&lt;strong&gt;坏的方面&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;先说说好的方面。&lt;/p&gt;
&lt;p&gt;字节跳动，作为国内目前的次顶级互联网公司（或许将来会成为顶级），手握今日头条与抖音等产品，发展迅猛，外界对其前景充满期待。自然，字节跳动完全拥有一家「创业公司」应有的工作环境与工作氛围，在我看来可谓是相当不错。&lt;/p&gt;
&lt;p&gt;不论是为&lt;strong&gt;外人&lt;/strong&gt;所津津乐道的各种福利（比如好吃且种类丰富的下午茶、零食与饮料），还是相对自由且灵活的管理制度，字节跳动提供了良好的工作环境。而年轻化的人员构成，现代化的管理系统，高效的办事流程，使得沟通顺畅，人际气氛和谐。或者再世俗一点，字节跳动的薪酬也足够高，且不论流传的各种天价 Offer ，仅仅是对于实习生的薪酬，我也不得不承认相当厚道。&lt;/p&gt;
&lt;p&gt;然而，字节跳动，一向以创业公司自称，Always Day 1，固然灵活且发展迅速，但无可避免地，这样做也充满了弊端（至少在我看来）。&lt;/p&gt;
&lt;p&gt;首先，强调快节奏的工作，保持创业，注重产出。这体现在我身边的同事们都显得格外忙碌（譬如我的 mentor ，有时候我会觉得他太忙了，以至于不好意思去用我琐碎的问题打断他的工作）。与之相比，有时候我会自我怀疑乃至感到愧疚：大伙就这么忙，为什么就我这么悠闲？这是一种健康的心态与工作氛围吗？我倾向于否定。除了忙碌，更严重的问题在于无止境的加班。不过由于作为实习生的我并不加班，就此便不多谈了。&lt;/p&gt;
&lt;p&gt;另一方面，短平快的工作产出，导致了无可避免的工作质量降低，这与所谓的「追求极致」是天生矛盾的，不论以何种冠冕堂皇的理由去辩解。即便以一个水平低下的实习生的视角审视组内的一些工作，我也觉得很多事情不能令人满意。比如，组内的代码庞杂而几乎没有任何文档，这使我想要了解某个 API 时不得不横跨多个微服务去看它的代码实现；而在代码中，注释往往是缺失的，偶尔见到几行注释，却是如下这种毫无作用仿佛模版生成一般的注释，形同虚设（我一开始怀疑这种注释是自动生成的，然而 git log 告诉我并非如此）。而代码本身，我无意去评判（毕竟我的水平也不足以让人信服我的评判），但至少，我认为许多地方可以写得更加「优雅」。&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// implement XXX method&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;XXX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再举一个例子，某日的组会上，某位同事提出了不错的编译性能优化方案（至少我觉得很不错，比起各种听上去花里胡哨的技术名词与方案，十分务实），也做了一些相对深入的工作来解决问题，却被质疑道：做这些对于我们的业务有什么帮助？现在这个不是我们的瓶颈所在，必要性在哪里？（原话不如此，但大意如此）我当时很想开口说一句「追求极致」，但想想还是算了，毕竟口号只是口号，谁信谁 XX，不如闷声发大财，多写一些没有文档与注释的代码，多实现一些产品所要求的特性，多拿一些薪水与奖金。&lt;/p&gt;
&lt;p&gt;再谈谈我所分配的工作内容。我极度怀疑，我们的项目组在招我进来之前，并没有想过他们是不是真的需要一个实习生，以及有哪些工作可以给实习生做，而是纯粹为了招聘而招聘。以后端开发之名招聘，却给我分配着测试的任务，而且还是女娲补天式的测试（毕竟，在之前，测试工作形同虚设，Jenkins 上的 regression test 已经坐了不知道多久的冷板凳了）。我并不是认为测试工作不重要，恰恰相反，我认为测试工作很重要，正因如此，我极度怀疑这样的工作分配是否合理。&lt;/p&gt;
&lt;p&gt;多提一句，在我实习的半途，我曾经向 mentor 提议换个工作内容，但是被拒绝了，要求我先「完成测试工作」，然后方可做点别的。然而讽刺的是，在我离职前不久，领导终于意识到测试工作的重要性，招聘了好些新的全职员工着力于此，计划以几个月的时间完成这项工作。所以，当初我一个人真的可以先完成这项工作再做点别的吗？&lt;/p&gt;
&lt;p&gt;因此，在实习的前两个月，我始终处于一种茫然的状态：过于宏大无当的工作方向，过于忙碌而难以给我指导的 mentor ，过于枯燥无味的工作内容。坦言之，从这样的工作安排中我既无法获得乐趣（这是支持我从初中开始编程的最大动力），也无法学到太多有用的东西（这是我前来实习的目的），更觉得自己所做的事情没法创造价值（这是我试图自我激励的幻想）。而至于实习的最后一个月，客观而言，因为新同事的加入，事态稍有改观，然而为时已晚，我已经失去了继续待下去的念想。&lt;/p&gt;
&lt;p&gt;多说不必，至此分别。我并不是贬低字节跳动，也不是贬低各位同事的能力（所谓代码质量，都是环境造就，与人的能力无关）。只是，经过三个月的实习，我意识到&lt;strong&gt;我和字节跳动并不搭（至少和现在的项目组不搭）&lt;/strong&gt;，那么，就此别过，祝大家和我都有美好的前程。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;后记：在提交了此份离职说明后，HR 和项目组领导均与我有所沟通，他们做了一些解释，但其实不必，我完全理解这些问题是取舍与权衡的产物，世上不可能有完美的公司，而我不过是在寻找最适合我的公司罢了。虽然我对字节跳动（或者具体一些，对这个项目组）不甚满意，但这次实习也并非失败，毕竟就实习而言，有所收获便已然足够，不能要求太多。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[二十岁，何妨吟啸且徐行]]></title><description><![CDATA[二十岁，大学历程已然过半，前方多歧路，今安在？]]></description><link>https://www.zackwu.com/posts/2019-11-26-just-move-on/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2019-11-26-just-move-on/</guid><pubDate>Tue, 26 Nov 2019 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;莫听穿林打叶声，何妨吟啸且徐行。竹杖芒鞋轻胜马，谁怕？一蓑烟雨任平生。 ——苏轼《定风波·莫听穿林打叶声》&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;又是一年的光阴。&lt;/p&gt;
&lt;p&gt;11 月 26 日，年年今日，是我的生日，也是我漫漫人生路上一次次的驻足回首。翻看自己往年今日所写的生日文章，彷佛黑夜里航行的船夫回望身后灯塔的点点星火。十八岁时，我充满无限的豪情壮志，相信黄金时代将要到来；十九岁时，心间常驻着千丝万缕的迷惘，所幸仍存不甘平庸的信念碎片。&lt;/p&gt;
&lt;p&gt;而此时此刻，在二十岁的生日，较之去年，在许多方面，我真真切切地觉察到，自己的心态已然发生了变化。当然，无所谓进步，无所谓沦落，仅仅是变化本身就值得记录。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;许多时候，追求最优解反而会让自己陷入无尽的困顿。&lt;/p&gt;
&lt;p&gt;自进入大学以来，我所经历的最大变化，是过往评价体系的崩塌与重建。不必赘言大学之前的一心向学，即便在大学，坦白而言，身边的环境所呈现的，依旧是 GPA 至上的“学在交大”。埋头求学诚然不是一个错误的选择，但是由于我所学的计算机专业的特殊性，我平日所接触的信息来源十分繁杂，充斥着各种相互碰撞的观点，也呈现着前途迥异的条条大路，它们之间并不存在明显的孰优孰劣，不免让人无法回避选择的痛苦。&lt;/p&gt;
&lt;p&gt;现在想来，十九岁时，我的迷惘归结下来，即是对将来自己的出路无所适从：出国留学，国内升学，抑或是早日进入职场。这几条路上，都有前人留下的无数足迹与丰碑，但也无可避免地悬着前人用泪水濯洗的种种失败警示牌。我曾尝试从中选出最优解，然而反复的纠结过后，我所意识到的，是这种比较的注定无结果：每当我觉得某个选择优于其他选择时，总会有某些信息刷新我的认知，让我匆忙撤回自己的决定。一如盲人同时摸象与鲸鱼，用片面的认知去比较复杂的事物，注定失败。&lt;/p&gt;
&lt;p&gt;然而周身四望，多数人并不似我一样在大二就对自己的出路“杞人忧天”，我既羡慕其埋头学习的安然与开怀游乐的自在，又常常感到自我怀疑与无所交流。不过，所幸在相当长一段时间的迷惘之后，时至今日，我渐渐想明白，与其在分岔路口拼命思索而陷入难以决断的痛苦，不如先找一条路淡然前行。&lt;/p&gt;
&lt;p&gt;坦言之，其实到现在，我心中依旧没有明确地划去或圈中某个选项，然而我所决定的，是与其坐而论道，不如起而行之。因此，不久之前，我便准备简历、参加面试，最终入职字节跳动，开始了人生中第一次的实习。自然，这并不意味着我现在已然决定在毕业后便开始工作，而不过是尽量用耳闻目睹替代道听途说，用亲身体会替代闷头苦思，收集更多的信息以便将来某一刻的决策。事实上，至今仅一个多月的实习经历，虽然体验尚未完整，但足以对我先前的不少认知动摇颇深，而这种体验是我在实习之前难以获得的。（言止于此，不多详谈，不过或许在将来某天，我会为这段实习经历写一篇总结。）&lt;/p&gt;
&lt;p&gt;夜雨潇潇，寒风吹彻。此时此刻，一边整理着思绪，一边零零碎碎地用键盘敲击出上面的只言片语，脑海中不觉回现出每次下班路途的场景：独自走在上海的街头，身旁是繁华的夜景与匆匆的行人，而我，不过是自顾自地快步向前。与之对比，我仍记得十八岁时骑着自行车猛冲下坡的飞扬与畅快，然而现在的我，确实只能尽量坚定且淡然地独自行着。&lt;/p&gt;
&lt;p&gt;虽然“黄金时代”不再，但我真心希望，自己可以“吟啸且徐行”。二十岁，祝自己生日快乐。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[本地 Git 仓库关联多个远程仓库的两种方法]]></title><description><![CDATA[通常情况下，一个本地 Git 仓库对应一个远程仓库，那么，如何使其同时关联多个远程仓库呢？]]></description><link>https://www.zackwu.com/posts/2019-09-11-ways-to-add-multiple-remote-repos-for-one-local-git-repo/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2019-09-11-ways-to-add-multiple-remote-repos-for-one-local-git-repo/</guid><pubDate>Wed, 11 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;背景&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%83%8C%E6%99%AF&quot; aria-label=&quot;背景 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;背景&lt;/h2&gt;
&lt;p&gt;通常情况下，一个本地 Git 仓库对应一个远程仓库，每次&lt;code class=&quot;language-text&quot;&gt;pull&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt;仅涉及本地仓库和该远程仓库的同步；然而，在一些情况下，一个本地仓库需要同时关联多个远程仓库，比如：同时将一个项目发布在 &lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt; 和 &lt;a href=&quot;https://coding.net/&quot;&gt;Coding&lt;/a&gt; 上，以兼顾国内外的访客（顺便一提，本站从近期起即是如此）。&lt;/p&gt;
&lt;p&gt;那么，如何让一个本地仓库同时关联多个远程仓库呢？&lt;/p&gt;
&lt;h2 id=&quot;方法-1每次pushpull时需分开操作&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%96%B9%E6%B3%95-1%E6%AF%8F%E6%AC%A1pushpull%E6%97%B6%E9%9C%80%E5%88%86%E5%BC%80%E6%93%8D%E4%BD%9C&quot; aria-label=&quot;方法 1每次pushpull时需分开操作 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;方法 1：每次&lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt;、&lt;code class=&quot;language-text&quot;&gt;pull&lt;/code&gt;时需分开操作&lt;/h2&gt;
&lt;p&gt;首先，查看本地仓库所关联的远程仓库：（假定最初仅关联了一个远程仓库）&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后，用&lt;code class=&quot;language-text&quot;&gt;git remote add &amp;lt;name&gt; &amp;lt;url&gt;&lt;/code&gt;添加一个远程仓库，其中&lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;可以任意指定（对应上面的&lt;code class=&quot;language-text&quot;&gt;origin&lt;/code&gt;部分），比如：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; coding.net git@git.coding.net:KeithNull/keithnull.github.io.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再次查看本地仓库所关联的远程仓库，可以发现成功关联了两个远程仓库：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt;
coding.net      git@git.coding.net:KeithNull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
coding.net      git@git.coding.net:KeithNull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;此后，若需进行&lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt;操作，则需要指定目标仓库，&lt;code class=&quot;language-text&quot;&gt;git push &amp;lt;repo&gt; &amp;lt;branch&gt;&lt;/code&gt;，对这两个远程仓库分别操作：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push origin master
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push coding.net master&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;同理，&lt;code class=&quot;language-text&quot;&gt;pull&lt;/code&gt;操作也需要指定从哪个远程仓库拉取，&lt;code class=&quot;language-text&quot;&gt;git pull &amp;lt;repo&gt; &amp;lt;branch&gt;&lt;/code&gt;，从这两个仓库中选择其一：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; pull origin master
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; pull coding.net master&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;方法-2push和pull无需额外操作&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%96%B9%E6%B3%95-2push%E5%92%8Cpull%E6%97%A0%E9%9C%80%E9%A2%9D%E5%A4%96%E6%93%8D%E4%BD%9C&quot; aria-label=&quot;方法 2push和pull无需额外操作 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;方法 2：&lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;pull&lt;/code&gt;无需额外操作&lt;/h2&gt;
&lt;p&gt;在方法 1 中，由于我们添加了多个远程仓库，在&lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;pull&lt;/code&gt;时便面临了仓库的选择问题。诚然如此较为严谨，但是在许多情况下，我们只需要保持远程仓库完全一致，而不需要进行区分，因而这样的区分便显得有些“多余”。&lt;/p&gt;
&lt;p&gt;同样地，先查看已有的远程仓库：（假定最初仅关联了一个远程仓库）&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后，&lt;strong&gt;不额外添加远程仓库，而是给现有的远程仓库添加额外的 URL&lt;/strong&gt;。使用&lt;code class=&quot;language-text&quot;&gt;git remote set-url -add &amp;lt;name&gt; &amp;lt;url&gt;&lt;/code&gt;，给已有的名为&lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;的远程仓库添加一个远程地址，比如：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote set-url &lt;span class=&quot;token parameter variable&quot;&gt;--add&lt;/span&gt; origin git@git.coding.net:KeithNull/keithnull.github.io.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再次查看所关联的远程仓库：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fetch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
origin  git@github.com:keithnull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
origin  git@git.coding.net:KeithNull/keithnull.github.io.git &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;push&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以看到，我们并没有如方法 1 一般增加远程仓库的数目，而是给一个远程仓库赋予了多个地址（或者准确地说，多个用于&lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt;的地址）。&lt;/p&gt;
&lt;p&gt;因此，这样设置后的&lt;code class=&quot;language-text&quot;&gt;push&lt;/code&gt; 和&lt;code class=&quot;language-text&quot;&gt;pull&lt;/code&gt;操作与最初的操作完全一致，不需要进行调整。&lt;/p&gt;
&lt;h2 id=&quot;总结&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%80%BB%E7%BB%93&quot; aria-label=&quot;总结 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;总结&lt;/h2&gt;
&lt;p&gt;以上是给一个本地仓库关联多个远程仓库的两种方法，二者各有优劣，不过出于简便考虑，我最终采用了方法 2。&lt;/p&gt;
&lt;p&gt;此外，上述内容中涉及到的 Git 指令略去了许多不常用的参数，如需更加详细的说明，可以查阅 &lt;a href=&quot;https://git-scm.com/docs/git-remote&quot;&gt;Git 文档&lt;/a&gt;，或者直接在命令行运行&lt;code class=&quot;language-text&quot;&gt;git remote --help&lt;/code&gt;。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[leptjson 项目总结：我从中学到了些什么？]]></title><description><![CDATA[跟着 Milo Yip 的教程，我顺利完成了 leptjson 项目，这一过程中，除了 JSON 与 C，我还学到了什么？]]></description><link>https://www.zackwu.com/posts/2019-09-02-summary-of-project-leptjson/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2019-09-02-summary-of-project-leptjson/</guid><pubDate>Mon, 02 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;简介&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%AE%80%E4%BB%8B&quot; aria-label=&quot;简介 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;简介&lt;/h2&gt;
&lt;p&gt;先简单地介绍一下背景。大概一个月之前，在日常刷知乎的过程中，偶然刷到了 &lt;a href=&quot;https://www.zhihu.com/people/miloyip&quot;&gt;Milo Yip&lt;/a&gt; 的 &lt;a href=&quot;https://zhuanlan.zhihu.com/p/22457315&quot;&gt;《从零开始的 JSON 库教程》&lt;/a&gt;，写得十分详细，而且在 &lt;a href=&quot;https://github.com/miloyip/json-tutorial/&quot;&gt;作者的 Github 仓库&lt;/a&gt; 中，有完整的代码与解析，因而顿时心动。拖了好一阵子，终于在十多天前决定开始动手。&lt;/p&gt;
&lt;p&gt;简单来说，leptjson（即这个项目）使用 C 语言，从零开始实现了一个 JSON 的解析器与生成器。虽然教程的作者把它拆分为了一系列的单元练习（每个单元给出部分代码，要求补写部分代码），但是在我的实践中，并没有完全遵照作者的设定，而是把“回合制”改成了模拟实际的灵活开发。&lt;/p&gt;
&lt;p&gt;这些天，跟着 Milo Yip 的教程，我顺利完成了 leptjson 项目，这一过程中，我学到了什么？&lt;/p&gt;
&lt;h2 id=&quot;c-与-json&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#c-%E4%B8%8E-json&quot; aria-label=&quot;c 与 json permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;C 与 JSON&lt;/h2&gt;
&lt;p&gt;最基础的，当然是这一项目所涉及的两种“语言”：C 与 JSON。&lt;/p&gt;
&lt;p&gt;C 语言是我的编程入门语言。在很久之前，我便用 C 语言写了不少程序，不过这些程序都是仅供 OJ 评判的算法题解，和常规意义上的程序，还是有一些差距。当然，后来在大学又继续学习了 C++，写了一些更加有实际意义的程序。但不管怎样，leptjson 可以说是我写的第一个贴近实际的 C/C++程序，让我更加深切地感受了利用 C/C++进行程序设计的体验。&lt;/p&gt;
&lt;p&gt;比起略显老旧的 XML，JSON 在近些年应用广泛。在各种场合，我其实已经多次接触并使用 JSON 进行数据传输，倒也对其毫不陌生，在 leptjson 的实现过程中，我所学到的，是 JSON 的一些格式细节和规范。&lt;/p&gt;
&lt;h2 id=&quot;浮点数与-unicode&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%B5%AE%E7%82%B9%E6%95%B0%E4%B8%8E-unicode&quot; aria-label=&quot;浮点数与 unicode permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;浮点数与 Unicode&lt;/h2&gt;
&lt;p&gt;把浮点数与 Unicode 并列，似乎有些不太合理，但于我而言，这样的组合却合情合理。&lt;/p&gt;
&lt;p&gt;在学习计算机组成课程时，粗略地了解过计算机内部表示数字的方法，但由于浮点数的复杂性，当时只是一掠而过，并没有太深入了解。而在完成 leptjson 项目时，由于需要解析 JSON 字符串中的数字，我不得不去了解浮点数的字符表示与二进制表示，更进一步，由于采取测试驱动开发的方法，我还需要为浮点数的解析寻找各种极端测试用例（比如最小的浮点数），“被迫”学习了浮点数表示的 IEEE 标准。&lt;/p&gt;
&lt;p&gt;而 Unicode，我对其第一印象建立于学习 Python 的过程中。最初我使用 Python 2，不论是编写爬虫还是处理文件，总是遇到各种奇怪的乱码，而网上搜索解决方案，便是无穷尽的使用&lt;code class=&quot;language-text&quot;&gt;encode&lt;/code&gt;与&lt;code class=&quot;language-text&quot;&gt;decode&lt;/code&gt;对字符串进行 GBK、UTF-8 等编码转换；而过了几年，则听说在 Python 3 中，如此的编码问题会少很多，原因则是 Python 3 使用 Unicode。而到了 leptjson，由于 JSON 解析过程中需要应对形如&lt;code class=&quot;language-text&quot;&gt;\uxxxx&lt;/code&gt;的转义字符，便较为详细地学习了 Unicode 与 UTF-8 编码。&lt;/p&gt;
&lt;p&gt;因此，浮点数与 Unicode，二者都是我似乎已然了解，却又一知半解的内容，通过 leptjson，廓清了一些模糊的概念。&lt;/p&gt;
&lt;h2 id=&quot;程序的内存管理&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86&quot; aria-label=&quot;程序的内存管理 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;程序的内存管理&lt;/h2&gt;
&lt;p&gt;内存管理，是一个我之前近乎从未涉及的内容：写算法题，内存管理毫无意义；做实际项目，往往使用 Python 等更加现代的语言，不需要我操心于此。而用 C 语言实现 leptjson，内存管理便是一道绕不过去的坎。&lt;/p&gt;
&lt;p&gt;在 leptjson 中，我大量使用了 C 的指针与动态内存分配，这便带来较为严重的内存泄漏隐患。而内存泄漏的 BUG，往往难以排除：肉眼看难以发现，程序测试也很难发现其存在。因此，在教程中，作者介绍了两款实用的工具：Windows 平台下 Visual C++的 C Runtime Library 与 Linux 平台的 valgrind。借助工具，可以快速发现程序中的内存管理问题，比如内存泄漏、访问非法地址等等。&lt;/p&gt;
&lt;p&gt;不过话说回来，即便有了工具的帮助，排查内存相关的 BUG 依旧是一件十分费力的工作，思路随着指针跳来跳去十分容易把自己弄晕。所以，我现在十分理解，为何在 C 之后，许许多多的程序语言都加上了自动内存回收等技术，不惜降低程序运行效率，以减轻开发者的负担。&lt;/p&gt;
&lt;h2 id=&quot;测试驱动开发tdd&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%B5%8B%E8%AF%95%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91tdd&quot; aria-label=&quot;测试驱动开发tdd permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;测试驱动开发（TDD）&lt;/h2&gt;
&lt;p&gt;如果一定要说，测试驱动开发（Test-Driven Development, TDD）是我所认为的最大收获。&lt;/p&gt;
&lt;p&gt;尽管在这个项目之前，我已经学习过软件工程课程，了解了不少软件开发的模式，但是至此我确是第一次听说 TDD。大概是由于课程与教材的过时，TDD 作为一种新兴的软件开发模式，我并没有在课堂上学到。&lt;/p&gt;
&lt;p&gt;简单来说，按我的理解，TDD 主要含义是：先写测试，再写实现，除了满足测试，绝不多写。似乎是一个很简单朴素的过程，但是根据我的实际体验，这样做使得我的开发过程十分愉快：比如下一步的目标是解析数字，那么首先，我需要编写关于解析数字的测试，确保覆盖所有可能的情况，此时尝试运行程序，会提示一系列的测试失败；然后，便针对这些新增的测试，实现对应的功能；再次尝试运行程序，如果通过所有测试，便完成了这一轮开发，否则，由于测试的存在，可以十分方便地定位错误的存在，进行解决。&lt;/p&gt;
&lt;p&gt;在 &lt;a href=&quot;https://github.com/izackwu/leptjson/commits/master&quot;&gt;我的 Commit 记录&lt;/a&gt; 中，可以看到多组&lt;code class=&quot;language-text&quot;&gt;tests&lt;/code&gt;与&lt;code class=&quot;language-text&quot;&gt;implementation&lt;/code&gt;的提交记录，二者交替出现，构成了 TDD 的轮廓。&lt;/p&gt;
&lt;h2 id=&quot;总结&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%80%BB%E7%BB%93&quot; aria-label=&quot;总结 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;总结&lt;/h2&gt;
&lt;p&gt;总的来说，虽然 leptjson 这一项目并不复杂（总计不超过 1000 行代码且有现成的教程指引），但是作为我第一个贴近实际的 C 语言项目，从中我切实学到了不少内容：C 与 JSON 语言本身，浮点数表示与 Unicode 等基础知识，内存管理，以及测试驱动开发的实践。&lt;/p&gt;
&lt;p&gt;最后，再次感谢 &lt;a href=&quot;https://www.zhihu.com/people/miloyip&quot;&gt;Milo Yip&lt;/a&gt; 花费大量时间与精力编写的教程！&lt;/p&gt;</content:encoded></item><item><title><![CDATA[在 Github 上使用 GPG 的全过程]]></title><description><![CDATA[如何利用 GPG，对每次 commit 进行签名以确保数据安全，同时信任 Github 的公钥？]]></description><link>https://www.zackwu.com/posts/2019-08-04-how-to-use-gpg-on-github/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2019-08-04-how-to-use-gpg-on-github/</guid><pubDate>Sun, 04 Aug 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;起因&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%B5%B7%E5%9B%A0&quot; aria-label=&quot;起因 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;起因&lt;/h2&gt;
&lt;p&gt;其实在很早之前 Github 就已经充分支持 GPG 密钥了，而在我之前使用 Github 的两年时间内，竟对此一无所知，实在有些“没见过世面”。直至近日，在一次偶然查看仓库的 commit 历史中，发现某些 commit 有一个不同寻常的绿色标记（Verified），不仅美观（？）而且看上去舒心，如图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/github-verified-screenshot.webp&quot; alt=&quot;漂亮的 Verified 标记&quot;&gt;&lt;/p&gt;
&lt;p&gt;点击这个标记，得知这一次 commit 是经过签名验证的（signed with a verified signature），因此，我便开始研究如何利用 GPG 对自己的每次 commit 进行签名验证。&lt;/p&gt;
&lt;h2 id=&quot;什么是-gpg&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BB%80%E4%B9%88%E6%98%AF-gpg&quot; aria-label=&quot;什么是 gpg permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;什么是 GPG&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;GnuPG is a complete and free implementation of the OpenPGP standard as
defined by &lt;a href=&quot;https://www.ietf.org/rfc/rfc4880.txt&quot;&gt;RFC4880&lt;/a&gt;(also known as &lt;em&gt;PGP&lt;/em&gt;). GnuPG allows you to encrypt and
sign your data and communications; it features a versatile key management
system, along with access modules for all kinds of public key
directories. GnuPG, also known as &lt;em&gt;GPG&lt;/em&gt;, is a command line tool with
features for easy integration with other applications.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;以上是从 &lt;a href=&quot;https://gnupg.org/&quot;&gt;GPG 网站&lt;/a&gt; 上摘取的部分简介，总的来说，GPG 的功能十分丰富，然而我这次主要是用它来对 Git 中的 commit 进行签名验证，所以需要做的事情也不算太复杂：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;生成自己的 GPG 密钥&lt;/li&gt;
&lt;li&gt;关联 GPG 公钥与 Github 账户&lt;/li&gt;
&lt;li&gt;设置利用 GPG 私钥对 commit 进行签名&lt;/li&gt;
&lt;li&gt;可选步骤：信任 Github 的 GPG 密钥&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;过程&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%BF%87%E7%A8%8B&quot; aria-label=&quot;过程 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;过程&lt;/h2&gt;
&lt;h3 id=&quot;安装-gpg&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%AE%89%E8%A3%85-gpg&quot; aria-label=&quot;安装 gpg permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;安装 GPG&lt;/h3&gt;
&lt;p&gt;由于我的目的是在 Git 中使用 GPG，而 Windows 版本的 Git 发行包中，已经包含了可用的 GPG 命令行。判断方法也很简单，打开 Git Bash，输入&lt;code class=&quot;language-text&quot;&gt;gpg --version&lt;/code&gt;，可以看到类似的 GPG 版本信息：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ gpg &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
gpg &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GnuPG&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2.2&lt;/span&gt;.16-unknown
libgcrypt &lt;span class=&quot;token number&quot;&gt;1.8&lt;/span&gt;.4
Copyright &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt; Free Software Foundation, Inc.
License GPLv3+: GNU GPL version &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; or later &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;https://gnu.org/licenses/gpl.html&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
This is &lt;span class=&quot;token function&quot;&gt;free&lt;/span&gt; software: you are &lt;span class=&quot;token function&quot;&gt;free&lt;/span&gt; to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /c/Users/---/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;不过需要说明的是，如果所安装的 Git 版本比较久远（比如我一开始所用的 Git 发行包是 2017 年的），那么很可能其包含的 GPG 版本过低，影响后续的操作，所以建议直接更新 Git 发行包至最新版本。&lt;/p&gt;
&lt;h3 id=&quot;生成自己的-gpg-密钥&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%94%9F%E6%88%90%E8%87%AA%E5%B7%B1%E7%9A%84-gpg-%E5%AF%86%E9%92%A5&quot; aria-label=&quot;生成自己的 gpg 密钥 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;生成自己的 GPG 密钥&lt;/h3&gt;
&lt;p&gt;打开 Git Bash，运行&lt;code class=&quot;language-text&quot;&gt;gpg --full-generate-key&lt;/code&gt;，根据提示，输入相应的个人信息（&lt;strong&gt;需要注意的是邮箱必须要使用在 Github 中验证过的邮箱&lt;/strong&gt;）、自定义密钥参数、设置私钥密码等等，即可生成自己的 GPG 密钥。（补充说明，使用&lt;code class=&quot;language-text&quot;&gt;gpg --gen-key&lt;/code&gt;亦可生成密钥，但是会略去自定义密钥参数的步骤，对于一般场合的使用倒也问题不大。）&lt;/p&gt;
&lt;p&gt;输出结果的末尾大致如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gpg: key DC3DB5873563E6B2 marked as ultimately trusted
gpg: revocation certificate stored as &lt;span class=&quot;token string&quot;&gt;&apos;/c/Users/---/.gnupg/openpgp-revocs.d/1BA074F113915706D141348CDC3DB5873563E6B2.rev&apos;&lt;/span&gt;
public and secret key created and signed.

pub   rsa2048 &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt;-08-04 &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;SC&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;expires: &lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;-08-03&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      1BA074F113915706D141348CDC3DB5873563E6B2
uid                      fortest &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;test@test.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
sub   rsa2048 &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt;-08-04 &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;expires: &lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;-08-03&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;需要记下的，是上述输出信息中的密钥 ID：&lt;code class=&quot;language-text&quot;&gt;1BA074F113915706D141348CDC3DB5873563E6B2&lt;/code&gt; 或者&lt;code class=&quot;language-text&quot;&gt;DC3DB5873563E6B2&lt;/code&gt;，后者是前者的简短形式。&lt;/p&gt;
&lt;p&gt;当然，如果没有及时将其记下也不要紧，可以运行&lt;code class=&quot;language-text&quot;&gt;gpg --list-keys&lt;/code&gt;，列出本地存储的所有 GPG 密钥信息，大致如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ gpg --list-keys
&lt;span class=&quot;token comment&quot;&gt;# some output is omitted here&lt;/span&gt;
pub   rsa2048 &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt;-08-04 &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;SC&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;expires: &lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;-08-03&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      1BA074F113915706D141348CDC3DB5873563E6B2
uid           &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultimate&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; fortest &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;test@test.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
sub   rsa2048 &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt;-08-04 &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;E&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;expires: &lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;-08-03&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;稍微解读一下这些结果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;pub&lt;/code&gt;其后的是该密钥的公钥特征，包括了密钥的参数（加密算法是 rsa，长度为 2048，生成于 2019-08-04，用途是 Signing 和 Certificating，一年之后过期）以及密钥的 ID。&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;uid&lt;/code&gt;其后的是生成密钥时所输入的个人信息。&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;sub&lt;/code&gt;其后的则是该密钥的子密钥特征，格式和公钥部分大致相同（E 表示用途是 Encrypting）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;关联-gpg-公钥与-github-账户&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%85%B3%E8%81%94-gpg-%E5%85%AC%E9%92%A5%E4%B8%8E-github-%E8%B4%A6%E6%88%B7&quot; aria-label=&quot;关联 gpg 公钥与 github 账户 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;关联 GPG 公钥与 Github 账户&lt;/h3&gt;
&lt;p&gt;还记得在上一步中记下的密钥 ID 吗？现在，我们需要根据这个 ID 来导出对应 GPG 密钥的公钥字符串。继续在 Git Bash 中，运行命令&lt;code class=&quot;language-text&quot;&gt;gpg --armor --export {key_id}&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ gpg &lt;span class=&quot;token parameter variable&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--export&lt;/span&gt; 1BA074F113915706D141348CDC3DB5873563E6B2
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBF1GT3wBCADC9Hb3HtDc69XzYlohVKvdL1KnK0FslJISRuF6S0sdoOiWo2wJ
OiYVplWguTSkrMytjnMsoysZVolkYluY1wk67NT8YuYfnu6LSuF/doihrRldnKmz
9NZWw+15MLnENKsWCtwNwcCGDeZNJACyyUMYk7nJeIiM72k3/rnsyEpHqB25W/Zf
1VBkwf/ShePZ2W+rUktJ8j1TZuxe2bQpJdHQ9EKWG50D8O3xk+N+xEg4pcXLMfwT
vnVpf2wINGLA6+3ypVMDipC0fgAnINBrrjiKsq2Sskv0O73D3sZlkOi0jgAhx+21
5dI2xHbcs3DrcZbWAF1xEA8wGsoyYQWoSCBrABEBAAG0F2ZvcnRlc3QgPHRlc3RA
dGVzdC5jb20+iQFUBBMBCAA+FiEEG6B08RORVwbRQTSM3D21hzVj5rIFAl1GT3wC
GwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ3D21hzVj5rJ3BQgA
nUusNKaf8SIWq1w4ZR6CKhZP+kz+5kOEBs3+qIXJV++9nbjs4jnqOnXJUUdpLS9E
HGYnd6XSeyqWmBAuFCcmld4VGIajYxgDbF11/ql5Gnbu26/jV7hnrBBK6Xn/6oV9
bBmLoT9xget5xFC6g2VE0EvneRqacUgMBCkvrMzcVnHmpkSOpjfXRAItnyK/bhia
8k/+5URO8v7Ao2+QO0zk8XzgGc5B8H/yItzDiKe7gpzdUyCviG8m/tkDUURzloY4
09wCmQWWzerbBHJT4RdpPqdTEtC6f4jTuT32zp5NtLpJ740WmSJly/8nAJ/0x3Vf
pVkzhsg9gVHe/JSFa6/hXbkBDQRdRk98AQgAyjXZ98VOgftRThuGuYxKhqahonLf
Ihu+NuNMFG6sGGzkm2T+1i4uKyM8T/kGdcTzTXE/SMHmrCMz94FNcQ77/OFLz5HY
8hjaz5Sun7iNmz5HGct8OrsP6gQeJ5ucqm3vDZmnwU/+J+wcTosv5mgWoBVob7jb
PBnoNVBQSVhD2ek4CDljn3PdReqYfe+ee8yn+6K1t9c1HHHMco3WpdgofUABd+7l
Q1LF8IpBRDvWgdMciAPaSthIqFT6R6xLQhXV8SUm0mr2/GXbYqIptjvy1JmUwNk3
jE3LOLYulZChRdvVg3Y+xgkVlMYLy3SBQ1EaTnUUsGYbhGQnOwDwVAlxgwARAQAB
iQE8BBgBCAAmFiEEG6B08RORVwbRQTSM3D21hzVj5rIFAl1GT3wCGwwFCQPCZwAA
CgkQ3D21hzVj5rLzvAf/QzfDOrhRz9AVLiAqus3Z/WfZY81sUiewNM+YdV9aODht
q4VE92SYHeR/b72+Fl62SRbDqxw7qG5FJGByuqo6nJjHEpnFzqB/pepTVDzlwvdn
JO46tmepFAChPBpeTTjTs2CF/BG0As0KxXQCpdFw4m8UdkZ7Olt1/LKnXrFmr1BA
jp2MvmAo38j2RyPTyXKWmJW+vC8DwmOGMoHCL6fM0TeaWey3rNxST7bbxPdRVc4Z
/26k450FEW5D+VInb9NuFYSoE2UXs6DgI1OWuuGvWePrtXHeQvuNbGdEdUwU14mf
msQ78G2MjX4AAYR5iNnQ/IWDBKbOWt3ajIoJuebArw&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;oHpZ
-----END PGP PUBLIC KEY BLOCK-----&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后，在 Github 的 &lt;a href=&quot;https://github.com/settings/keys&quot;&gt;SSH and GPG keys&lt;/a&gt; 中，新增一个 GPG key，内容即是上述命令的输出结果。&lt;/p&gt;
&lt;p&gt;再次提醒，GPG 密钥中个人信息的邮箱部分，必须使用在 Github 中验证过的邮箱，否则添加 GPG key 会提示未经验证。&lt;/p&gt;
&lt;h3 id=&quot;利用-gpg-私钥对-git-commit-进行签名&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%88%A9%E7%94%A8-gpg-%E7%A7%81%E9%92%A5%E5%AF%B9-git-commit-%E8%BF%9B%E8%A1%8C%E7%AD%BE%E5%90%8D&quot; aria-label=&quot;利用 gpg 私钥对 git commit 进行签名 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;利用 GPG 私钥对 Git commit 进行签名&lt;/h3&gt;
&lt;p&gt;首先，需要让 Git 知道签名所用的 GPG 密钥 ID：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--global&lt;/span&gt; user.signingkey &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;key_id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后，在每次 commit 的时候，加上&lt;code class=&quot;language-text&quot;&gt;-S&lt;/code&gt;参数，表示这次提交需要用 GPG 密钥进行签名：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-S&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果觉得每次都需要手动加上&lt;code class=&quot;language-text&quot;&gt;-S&lt;/code&gt;有些麻烦，可以设置 Git 为每次 commit 自动要求签名：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--global&lt;/span&gt; commit.gpgsign &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;但不论是否需要手动加上&lt;code class=&quot;language-text&quot;&gt;-S&lt;/code&gt;，在 commit 时皆会弹出对话框，需要输入该密钥的密码，以确保是密钥拥有者本人操作，如图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/git-commit-gpg.webp&quot; alt=&quot;GPG Signing on commit&quot;&gt;&lt;/p&gt;
&lt;p&gt;输入正确密码后，本次 commit 便被签名验证，push 到 Github 远程仓库后，即可显示出 Verified 绿色标记（由于&lt;code class=&quot;language-text&quot;&gt;fortest &amp;lt;test@test.com&gt;&lt;/code&gt;密钥的邮箱未经验证，所以此处实际用的是我本人的密钥进行签名）：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/github-verified-screenshot-again.webp&quot; alt=&quot;结果&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;可选步骤信任-github-的-gpg-密钥&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8F%AF%E9%80%89%E6%AD%A5%E9%AA%A4%E4%BF%A1%E4%BB%BB-github-%E7%9A%84-gpg-%E5%AF%86%E9%92%A5&quot; aria-label=&quot;可选步骤信任 github 的 gpg 密钥 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;可选步骤：信任 Github 的 GPG 密钥&lt;/h3&gt;
&lt;p&gt;事实上，在完成上述步骤后，已经可以&lt;strong&gt;基本&lt;/strong&gt;完全正常地同时使用 Github 和 GPG 了，那为什么还需要这一步骤呢？很简单，不妨用&lt;code class=&quot;language-text&quot;&gt;git log --show-signature&lt;/code&gt;试试查看本地的某个 Git 仓库的 commit 记录和签名信息：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log --show-signature
&lt;span class=&quot;token comment&quot;&gt;# some output is omitted&lt;/span&gt;
commit ec37d4af120a69dafa077052cfdf4f5e33fa1ef3 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; master&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
gpg: Signature made &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt; 年 08 月 &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; 日 &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;:52:29
gpg:                using RSA key 1BA074F113915706D141348CDC3DB5873563E6B2
gpg: Good signature from &lt;span class=&quot;token string&quot;&gt;&quot;fortest &amp;lt;test@test.com&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ultimate&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
Author: keithnull &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;keith1126@126.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Date:   Sun Aug &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;:52:29 &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt; +0800

    &lt;span class=&quot;token builtin class-name&quot;&gt;test&lt;/span&gt; GPG

commit 6937d638d950362f73bfbf28bc4a39d1700bf26b
gpg: Signature made &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt; 年 07 月 &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; 日 &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;:58:46
gpg:                using RSA key 4AEE18F83AFDEB23
gpg: Can&apos;t check signature: No public key
Author: Keith Null &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20233656&lt;/span&gt;+keithnull@users.noreply.github.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Date:   Wed Jul &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;:58:46 &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt; +0800

    Initial commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以发现，虽然所有的 commit 在 Github 中查看都是 Verified，但是有一些比较特殊：在 Github 网页端进行的操作，比如创建仓库。这些 commit 并没有用我们之前生成的密钥进行签名，而是由 Github 代为签名了。这样的结果就是，我们本地无法确认这些签名的真实性。&lt;/p&gt;
&lt;p&gt;为了解决这个问题，我们需要导入并信任 &lt;a href=&quot;https://github.com/web-flow.gpg&quot;&gt;Github 所用的 GPG 密钥&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;先是导入：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://github.com/web-flow.gpg &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; gpg &lt;span class=&quot;token parameter variable&quot;&gt;--import&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# curl&apos;s output is omitted&lt;/span&gt;
gpg: key 4AEE18F83AFDEB23: public key &lt;span class=&quot;token string&quot;&gt;&quot;GitHub (web-flow commit signing) &amp;lt;noreply@github.com&gt;&quot;&lt;/span&gt; imported
gpg: Total number processed: &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
gpg:               imported: &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后是信任（用自己的密钥为其签名验证，需要输入密码）：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ gpg --sign-key 4AEE18F83AFDEB23
pub  rsa2048/4AEE18F83AFDEB23
     created: &lt;span class=&quot;token number&quot;&gt;2017&lt;/span&gt;-08-16  expires: never       usage: SC
     trust: unknown       validity: full
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;  full  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;. GitHub &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;web-flow commit signing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;noreply@github.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

pub  rsa2048/4AEE18F83AFDEB23
     created: &lt;span class=&quot;token number&quot;&gt;2017&lt;/span&gt;-08-16  expires: never       usage: SC
     trust: unknown       validity: full
 Primary key fingerprint: 5DE3 E050 9C47 EA3C F04A  42D3 4AEE 18F8 3AFD EB23

     GitHub &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;web-flow commit signing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;noreply@github.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

Are you sure that you want to sign this key with your
key &lt;span class=&quot;token string&quot;&gt;&quot;Keith Null &amp;lt;keith1126@126.com&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;7C4BC917F7B12E8A&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

Really sign? &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y/N&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; y&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;至此，再尝试查看本地仓库的 commit 签名信息，则会发现所有的 commit 签名都已得到验证：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log --show-signature
&lt;span class=&quot;token comment&quot;&gt;# some output is omitted&lt;/span&gt;
commit 6937d638d950362f73bfbf28bc4a39d1700bf26b
gpg: Signature made &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt; 年 07 月 &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; 日 &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;:58:46
gpg:                using RSA key 4AEE18F83AFDEB23
gpg: Good signature from &lt;span class=&quot;token string&quot;&gt;&quot;GitHub (web-flow commit signing) &amp;lt;noreply@github.com&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;full&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
Author: Keith Null &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20233656&lt;/span&gt;+keithnull@users.noreply.github.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Date:   Wed Jul &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;:58:46 &lt;span class=&quot;token number&quot;&gt;2019&lt;/span&gt; +0800

    Initial commit&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;结束&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%BB%93%E6%9D%9F&quot; aria-label=&quot;结束 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;结束&lt;/h2&gt;
&lt;p&gt;经过这一番操作，Github 和 GPG 圆满结合在了一起，而我也得到了我想要的 Verified 标记。不过，GPG 的功能远非止于此，它还可以用来对文件、邮件等进行加密，还可以进行身份验证等等，都有待我去学习研究。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[十九岁，我不愿让一切走向庸俗]]></title><description><![CDATA[十九岁的我，选择怎样的生活？至少，我不愿让一切走向庸俗。]]></description><link>https://www.zackwu.com/posts/2018-11-26-say-no-to-being-mediocre-at-nineteen/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2018-11-26-say-no-to-being-mediocre-at-nineteen/</guid><pubDate>Mon, 26 Nov 2018 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;长安城里的一切都在无可避免的走向庸俗。 ——王小波《万寿寺》&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;十九年后，阳历与阴历再次重合在同一天。今天，是我的生日。&lt;/p&gt;
&lt;p&gt;想起去年今日，我踌躇满志，自以为在黄金时代一切都将遂我所愿。可是，生活又何曾如此？默默念着，默默行着，不必高歌，
现在的我只坚信我的坚信。不论如何，至少在我心中，我不愿让一切走向庸俗。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;身处何境，都难免有所妥协。&lt;/p&gt;
&lt;p&gt;回顾我的过去，尽管看上去有些光华，但其实我并非一个可以坚决到与自身所处境地相抗衡的人。
不同于那些天赋异禀，抑或毅力超人者，我的所作所为，其实无非是最符合所处环境的平庸之举。至于所赢得的赞美，在一定程度上，
也不过是对我“合作”而不“反抗”的认可。譬如学习，在高中，我所做的不过是好好学习，既没有参加竞赛或者有所成就的天分，又不如
那些把勤学苦练做到极致的人，虽然快乐而轻松，但，细想之下，我始终处于最平庸的舒适区内。&lt;/p&gt;
&lt;p&gt;至于现在，到了大学，枷锁似乎褪去，但我真的迎接到了自由吗？是的，我可以大声地宣告，我不在乎所谓的 GPA，所谓的奖学金，但面对
日常琐屑的课堂与作业，我能每一次都做到淡然吗？事实上，许多矛盾渐渐地为我所遇：用功学习与追求 GPA 是一回事吗？心态淡然与无所追逐是
一回事吗？诸如此等，或许我可以轻易地在口头上做出选择，但真正的抉择只在亲身面对时浮现。&lt;/p&gt;
&lt;p&gt;我可以什么都不做选择，所谓顺其自然。这样的生活，挺轻松。该上课了，我去了又回；布置作业了，我写完再上交……日子可以一天天这么过下去，
而且坦白说，这样做让我最后也能有一个不错的收获，一如按时耕作的农人。但，这样的生活不是平庸又是什么呢？一天天地，我在环境的作用下
顺之则昌了吗？&lt;/p&gt;
&lt;p&gt;所以，一切都在无可避免的走向平庸吗？&lt;/p&gt;
&lt;p&gt;平庸是最不费力的选择，但在十九岁，我相信，这一定不是最好的选择。&lt;/p&gt;
&lt;p&gt;其实说回环境，如果你处在一瓶清水中，但是里面混有一滴盐水，那么，是清水在影响你，还是那一滴盐水，或者说，这仅仅是你自己的选择？
面对这样的一问，我将如何作答其实都已经不重要了，因为答案早已经写好。&lt;/p&gt;
&lt;p&gt;在十九岁，我或许无所拥有，但我永远有权利去选择。即便面对生活渐渐走向庸俗的颓势，我依旧可以选择。&lt;/p&gt;
&lt;p&gt;学业繁重，总是有无穷无尽的作业与报告，但我永远可以选择以何种姿态去面对。即便完成各种小组作业纷繁复杂，我依旧
可以选择面对压力，独自一人去完成那些有意义的作业；即便某些课程有着学分与考核，我依旧可以选择将其流放，不为了
满足考核而自我压抑。&lt;/p&gt;
&lt;p&gt;前路漫漫，迷雾中有无数条通向远方的路，但我永远可以选择自己的方向。所谓学术与科研，或许是许多人推崇之道，但我始终持
着怀疑的态度，怀疑这条路是否与我不搭；所谓出国与进修，如果没有目标，单纯地为了出国而出国，又意义何在？
或者有着高远的目标，又是否愿意在失败之际委屈将就？所谓毕业后就职，似乎更加直截地宣告了平庸生活的加速到来……现在的我，或许
还没有自己的答案，但我始终保留着选择的权利，暂时不做选择亦是一种选择。&lt;/p&gt;
&lt;p&gt;当然，行胜于言。&lt;/p&gt;
&lt;p&gt;在十九岁生日的这天，我对自己许下各种誓言，一年之后，明天今日，和自己约定，再次共同回首。&lt;/p&gt;
&lt;p&gt;又或者，等下一个十九年，等下一次阳历与阴历相会，让中年的我回顾他的年轻岁月。&lt;/p&gt;
&lt;p&gt;但在今天，生日快乐。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Unable to find vcvarsall.bat?]]></title><description><![CDATA[Windows 平台下 Python 编译 C 拓展出错：Unable to find vcvarsall.bat 的解决过程。]]></description><link>https://www.zackwu.com/posts/2018-07-19-unable-to-find-vcvarsall-bat/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2018-07-19-unable-to-find-vcvarsall-bat/</guid><pubDate>Thu, 19 Jul 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;问题背景&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%97%AE%E9%A2%98%E8%83%8C%E6%99%AF&quot; aria-label=&quot;问题背景 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;问题背景&lt;/h2&gt;
&lt;p&gt;近日在学习一门计算机视觉的课程：CS231n, 在做 Assignment2 的时候，由于我自己实现的卷积和池化层效率很低（含有大量未优化的循环操作）,
作业要求我编译其提供的高效率版本 (C 拓展的形式）, 然后才能进行下一步的组装卷积神经网络。&lt;/p&gt;
&lt;p&gt;作业给的方法很简单，只需在&lt;code class=&quot;language-text&quot;&gt;cs231n/&lt;/code&gt;文件夹内运行如下代码：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;python setup.py build_ext &lt;span class=&quot;token parameter variable&quot;&gt;--inplace&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;但是当我这么做的时候，并没有成功，而是显示出错信息：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;error: Unable to find vcvarsall.bat&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;花费许久时间，尝试了不同方法，最后终于解决了这个问题，故写此文记录。&lt;/p&gt;
&lt;h2 id=&quot;解决过程&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%A7%A3%E5%86%B3%E8%BF%87%E7%A8%8B&quot; aria-label=&quot;解决过程 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;解决过程&lt;/h2&gt;
&lt;p&gt;遇到这个问题，我的第一感觉：编译出错肯定是 Windows 系统的原因，要么少了什么，要么错了什么。毕竟，不同于 Linux, 编译这个操作并不是 Windows
的强项。用出错信息在网上搜索了一下，大多数人表示这是由于系统中没有安装对 C++的支持导致的，而解决方法是安装 Visual Studio.&lt;/p&gt;
&lt;p&gt;但问题是，我的电脑上已经安装了最新的 VS2017, 且在安装时勾选了 C++和 Python 组件。更进一步，&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;这个文件也是存在的，
就在 VS 安装目录下的某个文件夹内。&lt;/p&gt;
&lt;p&gt;那么，会不会是 Python 没法正确地找到电脑中的&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;呢？&lt;/p&gt;
&lt;p&gt;继续搜索，有人表示查找这个文件的 Python 代码位于
&lt;code class=&quot;language-text&quot;&gt;%Python%\Lib\distutils\msvc9compiler.py&lt;/code&gt;文件的&lt;code class=&quot;language-text&quot;&gt;find_vcvarsall(version)&lt;/code&gt;函数中，代码如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;find_vcvarsall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;version&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;Find the vcvarsall.bat file
    At first it tries to find the productdir of VS 2008 in the registry. If
    that fails it falls back to the VS90COMNTOOLS env var.
    &quot;&quot;&quot;&lt;/span&gt;
    vsbase &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; VS_BASE &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; version
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        productdir &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Reg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get_value&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&quot;%s\Setup\VC&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; vsbase&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                   &lt;span class=&quot;token string&quot;&gt;&quot;productdir&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; KeyError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;debug&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Unable to find productdir in registry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        productdir &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; productdir &lt;span class=&quot;token keyword&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isdir&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productdir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        toolskey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VS%0.f0COMNTOOLS&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; version
        toolsdir &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;environ&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toolskey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; toolsdir &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isdir&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toolsdir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            productdir &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toolsdir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pardir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pardir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            productdir &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;abspath&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productdir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isdir&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productdir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;debug&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%s is not a valid directory&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; productdir&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;debug&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Env var %s is not set or invalid&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; toolskey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; productdir&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;debug&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;No productdir found&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
    vcvarsall &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productdir&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vcvarsall.bat&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isfile&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vcvarsall&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; vcvarsall
    log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;debug&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Unable to find vcvarsall.bat&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;代码看上去很复杂，但所做的无非是返回&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;文件的路径，那么，暂且不管为什么它找不到我电脑中的&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;,
如果我修改这段代码，让它直接返回硬编码的文件路径，或许就可以解决问题？因此，我做了如下修改：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;find_vcvarsall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;version&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    correct_vcvarsall&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;....../vcvarsall.bat&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;#the correct path of vcvarsall.bat&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; correct_vcvarsall&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;方法简单粗暴，但是很不幸，修改之后重新尝试编译，依旧是同样的错误。&lt;/p&gt;
&lt;p&gt;这就有些难以理解了：我已经让它返回正确的文件路径了，按理说已经可以找到&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;了，为什么还是不行呢？继续分析，两种可能性：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;这段代码并不是真正起作用的代码&lt;/li&gt;
&lt;li&gt;已有的&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;存在问题&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;由于我并不了解 Python 编译 C 拓展的具体过程，对于猜想 1 暂时无法验证，所以只能从猜想 2 入手。&lt;/p&gt;
&lt;p&gt;如果&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;有问题，那么解决这个问题的最简单方案就是重新安装 VS. 于是我彻底卸载了旧有的 VS2017, 但在准备重新下载安装时，
无意中发现了 &lt;a href=&quot;https://blogs.msdn.microsoft.com/pythonengineering/2016/04/11/unable-to-find-vcvarsall-bat/&quot;&gt;MSDN 上的一篇文章&lt;/a&gt;.
其作者简单解释了出错的原因并给出了解决方案：&lt;/p&gt;
&lt;figure&gt;
    &lt;a href=&quot;/images/unable-to-find-vcvarsall-bat-msdn.webp&quot;&gt;&lt;img src=&quot;/images/unable-to-find-vcvarsall-bat-msdn.webp&quot;&gt;&lt;/a&gt;
    &lt;figcaption&gt;MSDN: Solutions&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;对于 Windows 上的问题，MSDN 上的解决方案自然是最可能成功的，于是，按照其指引，我下载了
&lt;a href=&quot;http://go.microsoft.com/fwlink/?LinkId=691126&quot;&gt;Visual C++ Build Tools 2015&lt;/a&gt; 并安装（不安装整个 VS 是因为它太庞大了）.&lt;/p&gt;
&lt;p&gt;然后，见证奇迹的时候到了，再次尝试编译：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;running build_ext
building &apos;im2col_cython&apos; extension
creating build
creating build\temp.win-amd64-3.7
creating build\temp.win-amd64-3.7\Release
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD &quot;-IC:\Program Files\Python37\lib\site-packages\numpy\core\include&quot; &quot;-IC:\Program Files\Python37\include&quot; &quot;-IC:\Program Files\Python37\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\winrt&quot; /Tcim2col_cython.c /Fobuild\temp.win-amd64-3.7\Release\im2col_cython.obj
im2col_cython.c
c:\program files\python37\lib\site-packages\numpy\core\include\numpy\npy_1_7_deprecated_api.h(12) : Warning Msg: Using deprecated NumPy API, disable it by #defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
im2col_cython.c(2955): warning C4244: &apos;=&apos;: conversion from &apos;long&apos; to &apos;char&apos;, possible loss of data
im2col_cython.c(3333): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3342): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3351): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3360): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3817): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3826): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3835): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3844): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(4850): warning C4244: &apos;=&apos;: conversion from &apos;long&apos; to &apos;char&apos;, possible loss of data
im2col_cython.c(7107): warning C4244: &apos;=&apos;: conversion from &apos;long&apos; to &apos;char&apos;, possible loss of data
im2col_cython.c(30077): warning C4244: &apos;initializing&apos;: conversion from &apos;double&apos; to &apos;float&apos;, possible loss of data
im2col_cython.c(30083): warning C4244: &apos;initializing&apos;: conversion from &apos;double&apos; to &apos;float&apos;, possible loss of data
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO &quot;/LIBPATH:C:\Program Files\Python37\libs&quot; &quot;/LIBPATH:C:\Program Files\Python37\PCbuild\amd64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17134.0\ucrt\x64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17134.0\um\x64&quot; /EXPORT:PyInit_im2col_cython build\temp.win-amd64-3.7\Release\im2col_cython.obj /OUT:C:\MyCode\Learning-CS231n\assignment2\cs231n\im2col_cython.cp37-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.7\Release\im2col_cython.cp37-win_amd64.lib
im2col_cython.obj : warning LNK4197: export &apos;PyInit_im2col_cython&apos; specified multiple times; using first specification
   Creating library build\temp.win-amd64-3.7\Release\im2col_cython.cp37-win_amd64.lib and object build\temp.win-amd64-3.7\Release\im2col_cython.cp37-win_amd64.exp
Generating code
Finished generating code
LINK : fatal error LNK1158: cannot run &apos;rc.exe&apos;
error: command &apos;C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\x86_amd64\\link.exe&apos; failed with exit status 1158&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;嗯。.. 不同于之前找不到&lt;code class=&quot;language-text&quot;&gt;vcvarsall.bat&lt;/code&gt;的错误，现在有了很大的进展，但可惜的是，最后还是出错了。&lt;/p&gt;
&lt;p&gt;注意到出错消息的最后给了一个错误代码：&lt;code class=&quot;language-text&quot;&gt;exit status 1158&lt;/code&gt;, 以此搜索，非常顺利地，在 StackOverflow 上找到了一个
&lt;a href=&quot;https://stackoverflow.com/questions/43858836/python-installing-clarifai-vs14-0-link-exe-failed-with-exit-status-1158&quot;&gt;相同的问题&lt;/a&gt;
, 给出的答案看上去非常靠谱：&lt;/p&gt;
&lt;figure&gt;
    &lt;a href=&quot;/images/stackoverflow-exit-status-1158.webp&quot;&gt;&lt;img src=&quot;/images/stackoverflow-exit-status-1158.webp&quot;&gt;&lt;/a&gt;
    &lt;figcaption&gt;StackOverflow: Solutions&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;执行所述操作，然后再次见证奇迹：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;running build_ext
building &apos;im2col_cython&apos; extension
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD &quot;-IC:\Program Files\Python37\lib\site-packages\numpy\core\include&quot; &quot;-IC:\Program Files\Python37\include&quot; &quot;-IC:\Program Files\Python37\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\winrt&quot; /Tcim2col_cython.c /Fobuild\temp.win-amd64-3.7\Release\im2col_cython.obj
im2col_cython.c
c:\program files\python37\lib\site-packages\numpy\core\include\numpy\npy_1_7_deprecated_api.h(12) : Warning Msg: Using deprecated NumPy API, disable it by #defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
im2col_cython.c(2955): warning C4244: &apos;=&apos;: conversion from &apos;long&apos; to &apos;char&apos;, possible loss of data
im2col_cython.c(3333): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3342): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3351): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3360): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3817): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3826): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3835): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(3844): warning C4244: &apos;=&apos;: conversion from &apos;npy_intp&apos; to &apos;int&apos;, possible loss of data
im2col_cython.c(4850): warning C4244: &apos;=&apos;: conversion from &apos;long&apos; to &apos;char&apos;, possible loss of data
im2col_cython.c(7107): warning C4244: &apos;=&apos;: conversion from &apos;long&apos; to &apos;char&apos;, possible loss of data
im2col_cython.c(30077): warning C4244: &apos;initializing&apos;: conversion from &apos;double&apos; to &apos;float&apos;, possible loss of data
im2col_cython.c(30083): warning C4244: &apos;initializing&apos;: conversion from &apos;double&apos; to &apos;float&apos;, possible loss of data
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO &quot;/LIBPATH:C:\Program Files\Python37\libs&quot; &quot;/LIBPATH:C:\Program Files\Python37\PCbuild\amd64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17134.0\ucrt\x64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17134.0\um\x64&quot; /EXPORT:PyInit_im2col_cython build\temp.win-amd64-3.7\Release\im2col_cython.obj /OUT:C:\MyCode\Learning-CS231n\assignment2\cs231n\im2col_cython.cp37-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.7\Release\im2col_cython.cp37-win_amd64.lib
im2col_cython.obj : warning LNK4197: export &apos;PyInit_im2col_cython&apos; specified multiple times; using first specification
   Creating library build\temp.win-amd64-3.7\Release\im2col_cython.cp37-win_amd64.lib and object build\temp.win-amd64-3.7\Release\im2col_cython.cp37-win_amd64.exp
Generating code
Finished generating code&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;成功。&lt;/p&gt;
&lt;h2 id=&quot;总结&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%80%BB%E7%BB%93&quot; aria-label=&quot;总结 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;总结&lt;/h2&gt;
&lt;p&gt;编译这么一件小事，按理说一行命令就能解决的事，在 Windows 下变得如此麻烦，尽管我最终解决了问题，但实在耗费了不少精力。&lt;/p&gt;
&lt;p&gt;如果有得选，我选择 Linux, 就不会有这些麻烦了……&lt;/p&gt;</content:encoded></item><item><title><![CDATA[如何使部署在 Github Pages 上的网站采用 HTTPS]]></title><description><![CDATA[Github 与 Let's Encrypt 合作，让事情变得简单了许多。]]></description><link>https://www.zackwu.com/posts/2018-05-06-https-for-github-pages/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2018-05-06-https-for-github-pages/</guid><pubDate>Sun, 06 May 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;对于部署在 Github Pages 上的网站，如果使用默认的&lt;code class=&quot;language-text&quot;&gt;*.github.io&lt;/code&gt;域名，Github 会&lt;strong&gt;自动且强制&lt;/strong&gt;地使用 HTTPS，不需要任何额外操作。&lt;/p&gt;
&lt;p&gt;但对于绑定的自定义域名，原先的 Github 并不支持启用 HTTPS，可行的办法是通过 Cloudflare 的免费 DNS 解析服务，间接地得到 HTTPS，比较麻烦，因此一开始我并没有这个打算。&lt;/p&gt;
&lt;p&gt;然而就在前几天，无意间看到 Github 的官方消息，自定义域名也支持 HTTPS 了，而且操作简单，所以毫无疑问，肯定选择 HTTPS。&lt;/p&gt;
&lt;figure&gt;
    &lt;a href=&quot;/images/github-https-twitter.webp&quot;&gt;&lt;img src=&quot;/images/github-https-twitter.webp&quot;&gt;&lt;/a&gt;
    &lt;figcaption&gt;Github 在 Twitter 上发布的消息&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;根据官方的公告，如果自定义域名是用&lt;code class=&quot;language-text&quot;&gt;CNAME&lt;/code&gt;记录进行 DNS 解析，那么不需要做任何事情，就已经自动地支持了 HTTPS，而我的博客正好符合此条件。为了进一步提升安全性，我还在仓库设置中开启了&lt;code class=&quot;language-text&quot;&gt;Enforce HTTPS&lt;/code&gt;，强制将 HTTP 访问转为 HTTPS。&lt;/p&gt;
&lt;p&gt;这样之后，访问博客，就可以看到地址栏最左侧那个让人舒心的小绿锁了~&lt;/p&gt;
&lt;p&gt;然而，一个小问题出现了：博客中的图片无法正常加载，被 Firefox 以不安全的缘由拦截。何也？因为博客中的图片链接用的是 HTTP，混杂在 HTTPS 中，自然存在安全风险。解决方法也很简单，只需要打开 Jekyll 的配置文件&lt;code class=&quot;language-text&quot;&gt;_config.yml&lt;/code&gt;, 把&lt;code class=&quot;language-text&quot;&gt;url&lt;/code&gt;设置项由 HTTP 改为 HTTPS 即可，那么所有自动生成的图片链接&lt;code class=&quot;language-text&quot;&gt;{{site_url}}/images/x.png&lt;/code&gt;就会是 HTTPS 了。&lt;/p&gt;
&lt;p&gt;可以看到，以上的过程操作十分简单，这都要归功于 &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let’s Encrypt&lt;/a&gt; 项目和 Github 与其的合作。不免感慨，HTTPS 的推广，真的需要感谢这样的机构与公司存在。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[用 Jekyll 和 Github Pages 搭建博客之记录]]></title><description><![CDATA[我是如何用 Jekyll 搭建博客并部署到 Github Pages 上的。]]></description><link>https://www.zackwu.com/posts/2018-04-23-jekyll-and-github-pages/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2018-04-23-jekyll-and-github-pages/</guid><pubDate>Mon, 23 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;起因&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%B5%B7%E5%9B%A0&quot; aria-label=&quot;起因 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;起因&lt;/h2&gt;
&lt;p&gt;曾经用过 WordPress 建博客，虽然搭建过程很简单，甚至可以一键操作，而且功能全面，但是需要租用提供 PHP 和 MySQL 环境的服务器，需要一定的费用，而且对于一个简单的个人博客，不免显得有些过于笨重了。&lt;/p&gt;
&lt;p&gt;也考虑过在诸如 CSDN、掘金之类的博客平台直接创一个账户，简单省事，但是，这些网站的界面设计总觉得缺少美感而且不够自由发挥，便也作罢。&lt;/p&gt;
&lt;p&gt;更重要的是，正如前一篇文章中写的，有些话想说又不想被听见，所以倾向于不使用这些公众平台。&lt;/p&gt;
&lt;p&gt;最后，发现了 Jekyll 和 Github Pages 的组合，够轻量级，够自由定制，够私人，尽管稍显复杂，但对于程序员而言，复杂从来不是问题，只要优雅就好。&lt;/p&gt;
&lt;h2 id=&quot;总体流程&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%80%BB%E4%BD%93%E6%B5%81%E7%A8%8B&quot; aria-label=&quot;总体流程 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;总体流程&lt;/h2&gt;
&lt;p&gt;不同于 WordPress 需要连接数据库进行操作，Jekyll 仅仅是一个生成静态网页的工具，一次生成，只要不改变源代码，就可一直使用下去。因此，只需准备好博客的源码，上传到 Github 仓库，由 Github Pages 执行一次生成，便产生了我的博客网站直到下一次 commit 后重新生成。&lt;/p&gt;
&lt;p&gt;那么，我需要做的&lt;strong&gt;大体上&lt;/strong&gt;只有两件事：准备 Jekyll 的网站源码，部署到 Github Pages。&lt;/p&gt;
&lt;h2 id=&quot;jekyll-部分&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#jekyll-%E9%83%A8%E5%88%86&quot; aria-label=&quot;jekyll 部分 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Jekyll 部分&lt;/h2&gt;
&lt;p&gt;考虑到自己日益增长的审美需要和落后的前端水平的矛盾，我选择在现成的 Jekyll 主题基础上进行修改。&lt;/p&gt;
&lt;p&gt;Github Pages 上提供了少数可选的 Jekyll 主题，但 &lt;a href=&quot;http://jekyllthemes.org/&quot;&gt;Jekyll Themes&lt;/a&gt; 提供了更多而且更精美的主题。一番筛选后，最后选中了现在的主题，&lt;a href=&quot;https://github.com/TaylanTatli/Halve&quot;&gt;Halve&lt;/a&gt;,
很漂亮，同时也很简约。&lt;/p&gt;
&lt;figure&gt;
    &lt;a href=&quot;/images/halve-home-image.webp&quot;&gt;&lt;img src=&quot;/images/halve-home-image.webp&quot;&gt;&lt;/a&gt;
    &lt;figcaption&gt;&lt;a href=&quot;https://github.com/TaylanTatli/Halve&quot;&gt;Jekyll Theme: Halve&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;按照主题的说明，修改&lt;code class=&quot;language-text&quot;&gt;_config.yml&lt;/code&gt;进行基本的配置，并修改&lt;code class=&quot;language-text&quot;&gt;index.md&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;_posts/&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;_data/&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;_images/&lt;/code&gt;等内容，便完成了大部分工作。&lt;/p&gt;
&lt;p&gt;但在此基础上，我又做了一些其他的工作，更加深入一些。&lt;/p&gt;
&lt;h3 id=&quot;更改页面左右比例&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9B%B4%E6%94%B9%E9%A1%B5%E9%9D%A2%E5%B7%A6%E5%8F%B3%E6%AF%94%E4%BE%8B&quot; aria-label=&quot;更改页面左右比例 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;更改页面左右比例&lt;/h3&gt;
&lt;p&gt;Havle 主题默认是左侧图片和右侧内容各占 50%，给人一种类似书本平摊的感觉，诚然美观，但一定程度上影响了实用性。对于小屏幕设备（如 Surface），仅用 50%空间显示内容不免有些奢侈。 于是，我决定调整一下这个比例。&lt;/p&gt;
&lt;p&gt;在哪里调整呢？在&lt;code class=&quot;language-text&quot;&gt;_config.yml&lt;/code&gt;里面没有这个选项，分析一下，这种事情应该是由 CSS 实现的，那么便去&lt;code class=&quot;language-text&quot;&gt;assets/css/&lt;/code&gt;文件夹里面寻找，只有一个引用了其他文件的&lt;code class=&quot;language-text&quot;&gt;main.css&lt;/code&gt;，溯源而上，找到了&lt;code class=&quot;language-text&quot;&gt;assets/css/_sass/_site.scss&lt;/code&gt;，对应内容如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scss&quot;&gt;&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.block-left &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; left&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.content &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.block-right &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; right&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;overflow-y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.block-left,
.block-right &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; table&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;&gt; div &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; table-cell&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; middle&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.content &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;那么调整就很简单了，改为左侧 35%，右侧 65%：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scss&quot;&gt;&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.block-left &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 35%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; left&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.content &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.block-right &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 65%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; right&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;overflow-y&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.block-left,
.block-right &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; table&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;&gt; div &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; table-cell&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; middle&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.content &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;更改字体大小&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9B%B4%E6%94%B9%E5%AD%97%E4%BD%93%E5%A4%A7%E5%B0%8F&quot; aria-label=&quot;更改字体大小 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;更改字体大小&lt;/h3&gt;
&lt;p&gt;由于 Halve 主题原本面向的是英文用户，其字体的选用和大小都针对英文而设计，所以一开始我担心对于中文会显示效果不佳。不过经过测试，中文会采用默认的微软雅黑字体，差强人意，但尺寸上面，显得有些太大了，特别是在更改过页面比例后，长标题甚至会溢出左侧区域。&lt;/p&gt;
&lt;p&gt;因此，需要把字体调小一些。&lt;/p&gt;
&lt;p&gt;和调整页面比例类似，同样在&lt;code class=&quot;language-text&quot;&gt;assets/css/_sass/_site.scss&lt;/code&gt;内找到对应内容如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scss&quot;&gt;&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.section-title &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$white&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0.6&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;-ms-word-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; break-word&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;word-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; break-word&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;em &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; italic&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;span &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//lines omitted here&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.post-title-section &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.section-title &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 80px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;改为：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scss&quot;&gt;&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.section-title &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$white&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0.6&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;-ms-word-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; break-word&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;word-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; break-word&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;em &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; italic&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;span &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//lines omitted here&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.post-title-section &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;.section-title &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;采用圆形头像&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%87%87%E7%94%A8%E5%9C%86%E5%BD%A2%E5%A4%B4%E5%83%8F&quot; aria-label=&quot;采用圆形头像 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;采用圆形头像&lt;/h3&gt;
&lt;p&gt;主题默认头像是方形的，而且是透明背景的，显示出来效果十分优雅，但换上我自定义的头像后，美感全无。.. 尝试给图片去底，不是很成功，于是想着换成圆形。&lt;/p&gt;
&lt;p&gt;在 CSS 中，让图片以圆形显示其实是设置为 50%的圆角矩形，故在&lt;code class=&quot;language-text&quot;&gt;assets/css/_sass/_site.scss&lt;/code&gt;的。logo 中增加如下内容：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;scss&quot;&gt;&lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;img &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;-webkit-border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;-moz-border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 50%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这样子之后，效果相对可以接受了。&lt;/p&gt;
&lt;figure&gt;
    &lt;a href=&quot;/images/screenshot-jekyll-blog.webp&quot;&gt;&lt;img src=&quot;/images/screenshot-jekyll-blog.webp&quot;&gt;&lt;/a&gt;
    &lt;figcaption&gt;最终效果&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;github-pages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#github-pages&quot; aria-label=&quot;github pages permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Github Pages&lt;/h2&gt;
&lt;p&gt;为了方便省事，直接 fork 了 Halve 的仓库，改名为 keithnull.github.io 后，clone 到本地完成上述修改之后再 commit 上传。&lt;/p&gt;
&lt;p&gt;只要代码无误，Github Pages 便会在 commit 后生成网页，通过 &lt;a href=&quot;https://keithnull.github.io&quot;&gt;https://keithnull.github.io&lt;/a&gt; 即可访问。到这里，已经完成了博客的搭建。&lt;/p&gt;
&lt;p&gt;不过，额外的工作是自定义域名，毕竟 keithnull.github.io 是一个二级域名。&lt;/p&gt;
&lt;h2 id=&quot;自定义域名&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%9F%9F%E5%90%8D&quot; aria-label=&quot;自定义域名 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;自定义域名&lt;/h2&gt;
&lt;p&gt;申请域名、实名认证的步骤略过不提，在域名的 DNS 解析页面，需要做的是增加 DNS 解析如下：&lt;/p&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;记录类型&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;主机记录&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;记录值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;CNAME&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;@&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;keithnull.github.io&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;CNAME&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;www&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;keithnull.github.io&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;同时，在 Jekyll 文件夹内增加一个名为&lt;code class=&quot;language-text&quot;&gt;CNAME&lt;/code&gt;的文件，内容是自定义的域名。&lt;/p&gt;
&lt;p&gt;然后，等待。&lt;/p&gt;
&lt;p&gt;直到解析生效。&lt;/p&gt;
&lt;h2 id=&quot;最后&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9C%80%E5%90%8E&quot; aria-label=&quot;最后 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;最后&lt;/h2&gt;
&lt;p&gt;到这里，这个博客就已经完全搭建好了，正如现在它的样子。&lt;/p&gt;
&lt;p&gt;关于 Jekyll，其实还有许多可以定制的地方，留待之后用时了解吧。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;远在远方的风比远方更远。 —海子&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[起点，现在，未来]]></title><description><![CDATA[人总是有无法满足的表达欲望。]]></description><link>https://www.zackwu.com/posts/2018-04-22-the-start-of-my-blog/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2018-04-22-the-start-of-my-blog/</guid><pubDate>Sun, 22 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;人总是有无法满足的表达欲望。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;许多年前，初中的时候，那时的我一点都不懂编程，仅仅是在网上看了几个精美的博客，读了几篇教程，就想着要自己建一个网站写博客。照着贴吧上 WordPress 教程一步步模仿，又从网上下载了几个精美的 WordPress 主题，竟也做出了一个看得过去的博客。（那时我用的 WordPress 主题居然还是响应式的。）&lt;/p&gt;
&lt;p&gt;一开始，兴趣盎然，由于没有多少零花钱，便四处找免费的云主机（试过 BAE 还有一些不知名主机商），以及免费的域名（诸如二级域名和&lt;code class=&quot;language-text&quot;&gt;.tk&lt;/code&gt;域名），这样子坚持了一两个月，偶尔写写所谓的博文，感觉还挺好。&lt;/p&gt;
&lt;p&gt;后来，也许天助，混迹于贴吧的我在某个帖子中抽奖得到了一年的免费服务器，兴起之下，再买了一年的&lt;code class=&quot;language-text&quot;&gt;.com&lt;/code&gt; 域名，一切似乎渐入佳境，我的兴趣却难以理解地走向了消逝。&lt;/p&gt;
&lt;p&gt;那个博客的文章数就这样停在了二位数，直到域名回收，服务器到期，仅仅剩下几次数据备份的压缩包在我的旧电脑里。&lt;/p&gt;
&lt;p&gt;上了大学，闲时看看电影，读读小说，其间在简书和微信公众号也发了几次文章。&lt;/p&gt;
&lt;p&gt;许多时候，想说点什么又不想被人听见，犹豫之中表达欲便渐渐喑默，断断续续，上次写文已是去年。&lt;/p&gt;
&lt;p&gt;所以，不如重新开始，疏离公众，在一个完全私人的地方尽情表达吧。&lt;/p&gt;
&lt;p&gt;此处，此刻，未来。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[如果注定沉沦，清醒是一种悲剧]]></title><description><![CDATA[小说伊始，颂莲出场。她“白衣黑裙”、“留着齐耳的短发，用一条天蓝色的缎带箍住”，典型的民国时女大学生形象；然而“满脸尘土疲惫不堪”、“有点苍白”。]]></description><link>https://www.zackwu.com/posts/2017-12-15-sobriety-is-a-tragedy/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2017-12-15-sobriety-is-a-tragedy/</guid><pubDate>Fri, 15 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;本文是《妻妾成群》（苏童）的读后感。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;小说伊始，颂莲出场。她“白衣黑裙”、“留着齐耳的短发，用一条天蓝色的缎带箍住”，典型的民国时女大学生形象；然而“满脸尘土疲惫不堪”、“有点苍白”。&lt;/p&gt;
&lt;p&gt;她茫然地环顾，却渐渐地，泛出一种“醒目的寒意”。洗濯之后，一把推开傲慢的丫鬟雁儿，她说，“我是谁？你们迟早要知道的。”&lt;/p&gt;
&lt;p&gt;她是谁？陈佐千老爷新迎娶的四太太。&lt;/p&gt;
&lt;p&gt;一个女大学生，成为四太太，走入陈家的大宅院，似乎注定了将以悲剧作结。&lt;/p&gt;
&lt;p&gt;颂莲自然清楚自己的结局。&lt;/p&gt;
&lt;p&gt;父亲自杀后，继母问她何去何从，她淡然地冷笑着，“把我卖个好主吧”；初见陈佐千，她从提袋里掏出一大把小蜡烛，点上十九根，对自己说，“提前过生日吧，十九岁过完了。”如此清醒，更显悲凉。&lt;/p&gt;
&lt;p&gt;初到宅院，颂莲的年轻貌美是受宠的资本，因而她得到了陈佐千的极尽宠爱。在旁人看来，她的生活很如意。但在她心中，总有一种压抑的感伤挥之不去，像阴天。&lt;/p&gt;
&lt;p&gt;身处宅院，颂莲看见紫藤萝在秋风中摇曳，一天天清淡。她凝望紫藤架旁的废井，一种坚硬的凉意像石头一样慢慢敲她的身体……&lt;/p&gt;
&lt;p&gt;其他三位太太，就像所有人想象中的妻妾成群，她们互相算计、互相争斗，相处矛盾频频；而一位女大学生，却不像所有人想象中的那样思想进步有追求。颂莲很快便融入了宅院的环境，加入了妻妾成群的日常争斗之中。&lt;/p&gt;
&lt;p&gt;她假装失手，故意剪伤二太太卓云的耳朵；她因烧落叶与大太太毓如争吵；她强迫丫鬟雁儿吃下用来诅咒自己的草纸……一举一动，越来越像宅院中三位太太，越来越不像曾经的女大学生。&lt;/p&gt;
&lt;p&gt;是一种沉沦吧？但沉沦的痛苦不在于本身，而在于清醒。可颂莲一边沉沦，一边清醒。&lt;/p&gt;
&lt;p&gt;在与毓如争吵时，毓如斥骂“你颂莲在陈家算什么东西”，颂莲本应该毫不客气地回击，但她却没有。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;说对了，我算个什么东西？颂莲轻轻地像在自言自语，她微笑着转过身离开，再回头时已经泪光盈盈，她说，天知道你们又算个什么东西？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;沉沦于妻妾争斗中的她在此时清醒，她所沉沦的这一切又有什么意义呢？她痛苦地把自己关在屋子里，看见梳妆台上的大丽菊已然枯萎、发黑，那么，自己呢？&lt;/p&gt;
&lt;p&gt;飞浦（陈家少爷）来探望她，环顾她的屋子，突然说了一句，“我以为你房间里有好多书”。颂莲无奈地摊开双手，一本也没有，书现在对她已经没用了。毕竟，她已不再是那个女大学生，而是陈家四太太。&lt;/p&gt;
&lt;p&gt;独处时，颂莲面对镜子。她觉得里面的那个女人很陌生，她也很不喜欢那个女人。可是，她叹了口气，自己又能如何？她依旧选择做回陈家四太太。&lt;/p&gt;
&lt;p&gt;而随着内心的痛苦与纠缠，颂莲也渐渐失去了陈佐千的宠爱。因为不愿像卓云一样百般讨好，颂莲渐渐被冷落；而在陈佐千五十寿宴上，因为赌气不愿出席和当众亲了陈佐千一下，被他一把推开……颂莲的生活，沉沦中慢慢陷入深渊。&lt;/p&gt;
&lt;p&gt;颂莲和飞浦虚无地呷着酒，彼此无言。&lt;/p&gt;
&lt;p&gt;颂莲和梅珊面对面不说话，听墙上的挂钟嘀嗒嘀嗒响。&lt;/p&gt;
&lt;p&gt;颂莲凝视紫藤旁废井，隐隐约约，听见死去的鬼影在呼唤自己。&lt;/p&gt;
&lt;p&gt;亲眼目睹张扬恣睢的三太太梅珊因为偷情被投入废井后，她看见了陈家这座宅院的恐怖。&lt;/p&gt;
&lt;p&gt;她绝望地意识到，“一入宅门深似海”，自己再也没有可能摆脱这种压抑与沉沦。她清晰地看见，在将来的某一天，自己也会是梅珊一般的下场……&lt;/p&gt;
&lt;p&gt;而这一切，颂莲知道，她无力改变，只有沉沦。&lt;/p&gt;
&lt;p&gt;像沉入深渊的溺水者，意识清醒地感受着下坠，意识清醒地感受着窒息，意识清醒地等待着触底与死亡。&lt;/p&gt;
&lt;p&gt;多么痛苦。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[很遗憾，人们拒绝道歉]]></title><description><![CDATA[本文是电影《恐怖直播》的观后感。]]></description><link>https://www.zackwu.com/posts/2017-12-08-no-one-says-sorry/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2017-12-08-no-one-says-sorry/</guid><pubDate>Fri, 08 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;本文是电影《恐怖直播》的观后感。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;其实很少看韩国的电影，一是因为语言不通，二是因为不甚了解。而今天，看《恐怖直播》这部电影也纯属偶然——豆瓣的随机推荐结果。&lt;/p&gt;
&lt;p&gt;不过，在看完之后，从震撼中慢慢恢复，我可以毫不犹豫地给这部电影打上五星。这部电影，有着精彩的剧情和深刻的内涵。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;一句道歉的话就那么难吗&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%B8%80%E5%8F%A5%E9%81%93%E6%AD%89%E7%9A%84%E8%AF%9D%E5%B0%B1%E9%82%A3%E4%B9%88%E9%9A%BE%E5%90%97&quot; aria-label=&quot;一句道歉的话就那么难吗 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;“一句道歉的话就那么难吗？”&lt;/h2&gt;
&lt;p&gt;电影中，建筑工人朴鲁珪的儿子，为了给由于政府过错而死亡的三位建筑工人讨说法，在反复申告而未得之后，制造恐怖事件，引爆大桥，希望总统能够亲自向死去的工人道歉。&lt;/p&gt;
&lt;p&gt;为了这一句道歉，他精心筹划，打电话给电视台直播自己的恐怖行为，千般努力，却一无所得。在他死前，他问电视台主持人尹荣华，“一句道歉的话就那么难吗？”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-776c6ed8b931e305.webp&quot; alt=&quot;一句道歉的话就那么难吗&quot;&gt;&lt;/p&gt;
&lt;p&gt;难吗？难。&lt;/p&gt;
&lt;h2 id=&quot;利益面前对错被淡化&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%88%A9%E7%9B%8A%E9%9D%A2%E5%89%8D%E5%AF%B9%E9%94%99%E8%A2%AB%E6%B7%A1%E5%8C%96&quot; aria-label=&quot;利益面前对错被淡化 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;利益面前，对错被淡化&lt;/h2&gt;
&lt;p&gt;当尹荣华接到自称“朴鲁珪”的犯罪嫌疑人打来的电话时，很自然，他的第一反应是报警，但在稍加思索之后，他并没有这么做。&lt;/p&gt;
&lt;p&gt;他选择把这条消息作为独家新闻，换取自己的晋升。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-f2a6ad06032a3f3f.webp&quot; alt=&quot;独家新闻&quot;&gt;&lt;/p&gt;
&lt;p&gt;他神采飞扬，整理好自己的衣装与头发，得意地打电话给局长，谈着职位与独家消息的等价交换。在他看来，得到这条消息就是自己的幸运。&lt;/p&gt;
&lt;p&gt;而局长，答应了他的要求，亲自监督并指导他与“朴鲁珪”的直播，甚至毫不犹豫地给恐怖分子打钱以使其配合直播。但他这么做，完全是因为他与更高一层领导所做的收视率达到 70%便可成为本部长的交易。&lt;/p&gt;
&lt;p&gt;为此，他要求尹荣华在节目中一步步引导，反复提及“恐怖袭击”之类的词语，不顾事态发展而换取节目的收视率。&lt;/p&gt;
&lt;p&gt;在收视率达到 78%时，他满意而从容地离开演播室——之后的事，与他何干？&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-23ed8e7f031311bc.webp&quot; alt=&quot;事了拂衣去，深藏功与名。&quot;&gt;&lt;/p&gt;
&lt;p&gt;而千呼万唤不出来的总统先生，宁可牺牲大桥上的民众，也要保持国家的威信，坚持原则，拒绝向恐怖分子妥协。&lt;/p&gt;
&lt;p&gt;义正词严？但精明的局长点出了根源：要利用不妥协逼迫恐怖分子杀害民众，强加给他更多罪恶，从而能站在正义的立场讨伐“朴鲁珪”，挽回他所披露的事情对政府形象的破坏。&lt;/p&gt;
&lt;p&gt;他说，“人质死了恐怖事件才能结束。”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-a0402a7851fdbe97.webp&quot; alt=&quot;人质死了恐怖事件才能结束。&quot;&gt;
&lt;img src=&quot;/images/8817191-f8e35adeb2e2db60.webp&quot; alt=&quot;看透一切的局长&quot;&gt;&lt;/p&gt;
&lt;p&gt;如其所愿，尽管“朴鲁珪”有耐心面对一再拖延的政府辞令，但大桥终于坍圮，人质落入江中。最后，“朴鲁珪”被狙击手射杀，自由落体。&lt;/p&gt;
&lt;p&gt;事情结束了。&lt;/p&gt;
&lt;p&gt;总统先生发表声明，显示与恐怖分子斗争的决心与正义。&lt;/p&gt;
&lt;p&gt;见证了这一切的尹荣华，在废墟之中挣扎而起。可在此时，电话响起，他得知自己将作为替罪羊被检察院追责、起诉。&lt;/p&gt;
&lt;p&gt;毕竟，总要有一个交代。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-9ba1bd325011ac53.webp&quot; alt=&quot;替罪羊&quot;&gt;&lt;/p&gt;
&lt;p&gt;是的，尹荣华当然是有罪的，他收受黑钱，把妻子的新闻占为己有，他不是人们所认为的完美正义化身。但是，难道这一切的错误就可以仅仅归咎于他？&lt;/p&gt;
&lt;p&gt;利益面前，何止于上述角色，电影中的（几乎）每个人都不正义。对与错，早已被淡化，“朴鲁珪”又怎么等得到那句道歉？&lt;/p&gt;
&lt;h2 id=&quot;如果-在电影之外&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%A6%82%E6%9E%9C-%E5%9C%A8%E7%94%B5%E5%BD%B1%E4%B9%8B%E5%A4%96&quot; aria-label=&quot;如果 在电影之外 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;如果。.. 在电影之外？&lt;/h2&gt;
&lt;p&gt;有人说，韩国上世纪废除电影审查制度是一个转捩点，自此，各种反映社会现实的深刻题材得以展现。&lt;/p&gt;
&lt;p&gt;就这部电影而言，确实，可以窥见韩国社会的些许。&lt;/p&gt;
&lt;p&gt;而究竟窥见了什么，原本我想了很多，也写下了不少，但最终，我还是删掉了这些文字。&lt;/p&gt;
&lt;p&gt;因为在写的过程中，我渐渐意识到，当各种利益交织，每个人心怀迥异，事情有着无限的可能，用几段文字所“分析”出来的，若非浮浅寡淡，便是谬谈。&lt;/p&gt;
&lt;h2 id=&quot;最后&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E6%9C%80%E5%90%8E&quot; aria-label=&quot;最后 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;最后&lt;/h2&gt;
&lt;p&gt;在影片的结尾，尹荣华接过“朴鲁珪”的引爆器，背靠墙壁，闭上双眼，按下引爆键。&lt;/p&gt;
&lt;p&gt;随着电视台大楼的轰然倒塌，对于真相，对于对错，那些没有结果的挣扎选择了毁灭。&lt;/p&gt;
&lt;p&gt;或许，这真的是唯一的出路了吧。&lt;/p&gt;
&lt;p&gt;可是，很遗憾，就算引爆一切，也没有人道歉啊！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-f08d06162c36cc21.webp&quot; alt=&quot;最后，毁灭&quot;&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[十八岁，我知道我的黄金时代正在到来]]></title><description><![CDATA[那一天我二十一岁，在我一生的黄金时代。我有好多奢望。我想爱，想吃，还想在一瞬间变成天上半明半暗的云。——王小波《黄金时代》]]></description><link>https://www.zackwu.com/posts/2017-11-26-my-golden-age-at-eighteen/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2017-11-26-my-golden-age-at-eighteen/</guid><pubDate>Sun, 26 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;那一天我二十一岁，在我一生的黄金时代。我有好多奢望。我想爱，想吃，还想在一瞬间变成天上半明半暗的云。——王小波《黄金时代》&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;今天，是我的十八岁生日。&lt;/p&gt;
&lt;p&gt;所以，不妨在这一天，写下我这些日子里的所有念想。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;脱身于九年制义务教育和三年高中，用二十分钟高铁的距离，十八岁的我离开了曾经的学校与城市，开始了一种新的生活。&lt;/p&gt;
&lt;p&gt;当然，大学的生活并非如我曾经憧憬的那样完美。这里不是理想世界，但我可以确定，这里将见证我的黄金时代，毫无疑问。&lt;/p&gt;
&lt;p&gt;午后，骑自行车穿过校园，初冬的阳光依旧灿烂。&lt;/p&gt;
&lt;p&gt;在一个隧道面前，我放开刹车，我和我的自行车积攒的势能自由地转换为我们共同的动能。我感受到寒冽的风透过阳光，但我的外套大大方方地敞开，兜着满满的风，张扬地挥动。&lt;/p&gt;
&lt;p&gt;隧道墙壁的涂鸦鲜艳夺目，不必去细看画了些什么、写了些什么，五彩的颜料本身就是一种强烈的存在。所有路过的人都没法回避它们的鲜艳。&lt;/p&gt;
&lt;p&gt;那一刻，心情明朗到无以复加。我想放声大笑，我想高歌一曲。或者说，我什么也不需要做，因为无论什么都不足以表达。&lt;/p&gt;
&lt;p&gt;因为十八岁，我的黄金时代正在到来。&lt;/p&gt;
&lt;p&gt;我确信，在我的十八岁，我将拥有最精彩的生活。不论生活是什么形状，我都将让它成为我的黄金时代。&lt;/p&gt;
&lt;p&gt;我不必去理会众人的看法，不必为了零点几的 GPA 之差而耿耿于怀，不必被限制在有限的天地，我要我的自由与快乐，它们不容许被侵吞。&lt;/p&gt;
&lt;p&gt;我要无止地读书，把这些年想读的书通通读完。用一本本的书，填满我的借阅清单。有谁规定了理工科的学生应该只潜心数理，而不能多读文学？我会骄傲地在我的书单上打勾，我也会在某个悠闲的午后、或者安然的深夜，用我的文字捕捉那些闪烁的念头。&lt;/p&gt;
&lt;p&gt;我要尽情地奔跑，要更自由挥洒的汗水。我要绕着运动场，一圈圈地奔跑；也要沿着小径，穿过每个路口。夜晚的校园，不属于任何人的车辙，只属于我的足迹。当呼吸开始急促，脚步不再轻松，我知道，最美好的时刻将是我到达终点的那一瞬间。&lt;/p&gt;
&lt;p&gt;我要疯狂地写代码，这不只是我的专业，更是我的爱好。我将怀着最初的热忱，写下一行行优雅的代码，它们拼凑出属于我的独特世界。我不会为了考试的要求而死磕那些无聊而不美的代码，不会把编程变成枯燥的搭积木。这不是我要的，也不会是我将得到的。&lt;/p&gt;
&lt;p&gt;我要做自由而快乐的自己，那是我原本的样子，也应该是我将来的样子。&lt;/p&gt;
&lt;p&gt;十八岁，我知道，我的黄金时代正在到来。&lt;/p&gt;
&lt;p&gt;生日快乐。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Checkio 探险日志->Home->The Most Wanted Letter]]></title><description><![CDATA[本文是 CheckiO 探险日志系列第一篇]]></description><link>https://www.zackwu.com/posts/2017-11-18-checkio-home-the-most-wanted-letter/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2017-11-18-checkio-home-the-most-wanted-letter/</guid><pubDate>Sat, 18 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;本文是 CheckiO 探险日志系列第一篇&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;系列前言&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E7%B3%BB%E5%88%97%E5%89%8D%E8%A8%80&quot; aria-label=&quot;系列前言 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;系列前言&lt;/h2&gt;
&lt;p&gt;近日，在知乎上看到一个回答，推荐 &lt;a href=&quot;https://checkio.org/&quot;&gt;CheckiO&lt;/a&gt; 作为练习 Python 的绝佳网站。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;好奇心让我点进去，而其魅力让我流连。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 CheckiO，我可以完成 Python 的练习题，在线测试解法的正确性，并且更棒的是，&lt;strong&gt;可以查看全球各地的程序员们所想出的各种奇妙解法&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;如其自述，“Online game for Python and JavaScript coders”，CheckiO 实在是很有趣，因此，从现在起，我开始了我的探险历程。&lt;/p&gt;
&lt;p&gt;而这一系列的探险日志，就从这里开始吧。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;home-the-most-wanted-letter&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#home-the-most-wanted-letter&quot; aria-label=&quot;home the most wanted letter permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Home-&gt;The Most Wanted Letter&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;题目描述&lt;/strong&gt;：编写一个函数，返回字符串中出现次数最多的字符。（详见 &lt;a href=&quot;https://py.checkio.org/mission/most-wanted-letter/&quot;&gt;The Most Wanted Letter&lt;/a&gt;）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题思路&lt;/strong&gt;：统计每个字符的出现次数，然后找到其中次数最多者。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;0-我的解法&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#0-%E6%88%91%E7%9A%84%E8%A7%A3%E6%B3%95&quot; aria-label=&quot;0 我的解法 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;0. 我的解法&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    counter&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;26&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; c &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isalpha&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            counter&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    maxn&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; counter&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;counter&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;maxn&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            maxn&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;i
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;maxn&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其实可以看出，我的这种写法带有很浓的 C 语言的风格，就像在操作 C 语言中的数组一样。&lt;/p&gt;
&lt;p&gt;然而，这样的写法非常的原始，仅仅利用了 Python 中最低级的一些语法，没有发挥出** Python 的优雅特性**，不够“Pythonic”。&lt;/p&gt;
&lt;p&gt;那么，怎样写才是优雅的呢？不妨参见 CheckiO 上其他人的写法：&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-使用-max-函数&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%E4%BD%BF%E7%94%A8-max-%E5%87%BD%E6%95%B0&quot; aria-label=&quot;1 使用 max 函数 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. &lt;a href=&quot;https://py.checkio.org/mission/most-wanted-letter/publications/bryukh/python-3/max-count/?ordering=most_voted&amp;#x26;filtering=choice&quot;&gt;使用 max 函数&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; string
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ascii_lowercase&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;首先，关注一下 ascii_lowercase，一个位于 string 模块中的常量。该模块中其他的常量一并罗列如下：&lt;/p&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;字符串常量&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.ascii_letters&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;The concatenation of the ascii_lowercase and ascii_uppercase constants described below. This value is not locale-dependent.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.ascii_lowercase&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;The lowercase letters ‘abcdefghijklmnopqrstuvwxyz’. This value is not locale-dependent and will not change.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.ascii_uppercase&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;The uppercase letters ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’. This value is not locale-dependent and will not change.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.digits&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;The string ‘0123456789’.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.hexdigits&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;The string ‘0123456789abcdefABCDEF’.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.octdigits&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;The string ‘01234567’.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.punctuatio&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;String of ASCII characters which are considered punctuation characters in the C locale.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.printable&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;String of ASCII characters which are considered printable. This is a combination of digits, ascii_letters, punctuation, and whitespace.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;string.whitespace&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;A string containing all ASCII characters that are considered whitespace. This includes the characters space, tab, linefeed, return, formfeed, and vertical tab.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;其次，关注 max() 函数。在 Python 中，max() 是一个非常强大的内建函数，其官方文档如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;max(iterable, *[, key, default])&lt;/p&gt;
&lt;p&gt;max(arg1, arg2, *args[, key])&lt;/p&gt;
&lt;p&gt;Return the largest item &lt;strong&gt;in an iterable or the largest of two or more arguments&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If one positional argument is provided&lt;/strong&gt;, it should be an iterable. The largest item in the iterable is returned. &lt;strong&gt;If two or more positional arguments are provided&lt;/strong&gt;, the largest of the positional arguments is returned.&lt;/p&gt;
&lt;p&gt;There are &lt;strong&gt;two optional keyword-only arguments&lt;/strong&gt;. The key argument specifies &lt;strong&gt;a one-argument ordering function&lt;/strong&gt; like that used for list.sort(). The default argument specifies &lt;strong&gt;an object to return if the provided iterable is empty&lt;/strong&gt;. If the iterable is empty and default is not provided, a ValueError is raised.&lt;/p&gt;
&lt;p&gt;If multiple items are maximal, the function &lt;strong&gt;returns the first one encountered&lt;/strong&gt;. This is consistent with other sort-stability preserving tools such as sorted(iterable, key=keyfunc, reverse=True)[0] and heapq.nlargest(1, iterable, key=keyfunc).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;可以看出，max() 完美地解决了我们的问题。&lt;/p&gt;
&lt;h3 id=&quot;2-使用-lambda-匿名函数&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%E4%BD%BF%E7%94%A8-lambda-%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0&quot; aria-label=&quot;2 使用 lambda 匿名函数 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. &lt;a href=&quot;https://py.checkio.org/mission/most-wanted-letter/publications/veky/python-3/key/?ordering=most_voted&amp;#x26;filtering=choice&quot;&gt;使用 lambda 匿名函数&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; string &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; ascii_lowercase &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; letters
checkio &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;letters&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;lambda 匿名函数是函数式编程中一个极其重要的组成，有了它，我们可以大幅缩短缩写函数的代码量，并保持较高的可读性。&lt;/p&gt;
&lt;p&gt;正如这种解法，原理与解法 1 完全一致，但利用 lambda 函数可以让代码更加简洁。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;也更加优雅。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-使用-counter-对象&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-%E4%BD%BF%E7%94%A8-counter-%E5%AF%B9%E8%B1%A1&quot; aria-label=&quot;3 使用 counter 对象 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. &lt;a href=&quot;https://py.checkio.org/mission/most-wanted-letter/publications/ForeverYoung/python-3/first/?ordering=most_voted&amp;#x26;filtering=choice&quot;&gt;使用 Counter 对象&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; collections &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Counter
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;x &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isalpha&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;values&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;x &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其实这种解法，是解法 1 的复杂化，用 Counter 对象替代字符串的 count() 函数，我个人并不认可。&lt;/p&gt;
&lt;p&gt;不过，关于 Counter，还是有很多值得我们关注的。详细的描述可以参见 Python 的 &lt;a href=&quot;https://docs.python.org/3/library/collections.html?highlight=counter#collections.Counter&quot;&gt;官方文档&lt;/a&gt; 或者 &lt;a href=&quot;https://www.cnblogs.com/nisen/p/6052895.html&quot;&gt;这篇文章&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;在此，摘录并整理部分来自上述两处的内容。&lt;/p&gt;
&lt;h4 id=&quot;创建&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%88%9B%E5%BB%BA&quot; aria-label=&quot;创建 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;创建：&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;class collections.Counter(&lt;strong&gt;[iterable-or-mapping]&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;A Counter is &lt;strong&gt;a dict subclass&lt;/strong&gt; for counting hashable objects. It is an &lt;strong&gt;unordered&lt;/strong&gt; collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. The Counter class is similar to bags or multisets in other languages.&lt;/p&gt;
&lt;p&gt;Elements are counted from an iterable or initialized from another mapping (or counter).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;举例如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;                           &lt;span class=&quot;token comment&quot;&gt;# 创建一个新的空 counter&lt;/span&gt;
c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abcasdf&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;# 一个迭代对象生成的 counter&lt;/span&gt;
c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;red&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;yellow&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;# 一个映射生成的 counter&lt;/span&gt;
c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cats&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dogs&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;             &lt;span class=&quot;token comment&quot;&gt;# 关键字参数生成的 counter&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;使用&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BD%BF%E7%94%A8&quot; aria-label=&quot;使用 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;使用：&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Counter objects have a dictionary interface except that they &lt;strong&gt;return a zero count for missing items&lt;/strong&gt; instead of raising a KeyError.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Counter objects support three methods beyond those available for all dictionaries:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;elements()&lt;/p&gt;
&lt;p&gt;Return an iterator over elements repeating each as many times as its count. Elements are returned &lt;strong&gt;in arbitrary order&lt;/strong&gt;. If an element’s count is less than one, elements() will ignore it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;most_common([n])&lt;/p&gt;
&lt;p&gt;Return &lt;strong&gt;a list of the n most common elements and their counts from the most common to the least&lt;/strong&gt;. If n is omitted or None, most_common() returns all elements in the counter. Elements with equal counts are ordered arbitrarily.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;subtract([iterable-or-mapping])&lt;/p&gt;
&lt;p&gt;Elements are subtracted from an iterable or from another mapping (or counter). Like dict.update() but subtracts counts instead of replacing them. Both inputs and outputs may be zero or negative.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The usual dictionary methods are available for Counter objects except for two which work differently for counters.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;fromkeys(iterable)&lt;/p&gt;
&lt;p&gt;This class method is not implemented for Counter objects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;update([iterable-or-mapping])&lt;/p&gt;
&lt;p&gt;Elements are counted from an iterable or added-in from another mapping (or counter). Like dict.update() but &lt;strong&gt;adds counts instead of replacing them&lt;/strong&gt;. Also, the iterable is expected to be a sequence of elements, not a sequence of (key, value) pairs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;可以看出，Counter 对象对于计数方面有着非常方便的使用，同时也可以基本上按照普通 dict 对象的方法来处理。&lt;/p&gt;
&lt;p&gt;需要注意的是，Counter 对象还支持&lt;strong&gt;直接用运算符来操作&lt;/strong&gt;，官方文档中的示例如下：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; d &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; d                       &lt;span class=&quot;token comment&quot;&gt;# add two counters together:  c[x] + d[x]&lt;/span&gt;
Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; d                       &lt;span class=&quot;token comment&quot;&gt;# subtract (keeping only positive counts)&lt;/span&gt;
Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; d                       &lt;span class=&quot;token comment&quot;&gt;# intersection:  min(c[x], d[x])&lt;/span&gt;
Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; d                       &lt;span class=&quot;token comment&quot;&gt;# union:  max(c[x], d[x])&lt;/span&gt;
Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; e &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;e                          &lt;span class=&quot;token comment&quot;&gt;# equal to Counter() + e&lt;/span&gt;
Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;e
Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;# equal to Counter() - e&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;4-使用正则表达式&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F&quot; aria-label=&quot;4 使用正则表达式 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. &lt;a href=&quot;https://py.checkio.org/mission/most-wanted-letter/publications/ale1ster/python-3/counter/?ordering=most_voted&amp;#x26;filtering=choice&quot;&gt;使用正则表达式&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; collections &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Counter
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Counter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sub&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;[^a-z]&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                 key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这种解法。.. 一言难尽。初看给人一种眼花缭乱的炫技感，仔细分析之后，只剩下膜拜。&lt;/p&gt;
&lt;p&gt;篇幅所限，不引申关于 re 的知识，仅仅分析这段程序的原理。&lt;/p&gt;
&lt;p&gt;首先，先看看函数的返回值是什么。&lt;code class=&quot;language-text&quot;&gt;sorted(...)&lt;/code&gt;返回排序之后的一个&lt;strong&gt;列表&lt;/strong&gt;，而我们取这个列表的 [0][0] 位置的内容作为返回值。&lt;/p&gt;
&lt;p&gt;那么，这个列表是什么？初步感觉，应该相当于 C 语言中的一个二维数组，才能取其 [0][0]。回到&lt;code class=&quot;language-text&quot;&gt;sorted()&lt;/code&gt;函数，我们知道，它的第一个参数应该是排序前的列表：&lt;code class=&quot;language-text&quot;&gt;list(Counter(re.sub(&apos;[^a-z]&apos;, &apos;&apos;, text.lower())).items())&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;不妨从内向外，解读一下这个列表：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;re.sub(&apos;[^a-z]&apos;, &apos;&apos;, text.lower())&lt;/code&gt;是一个用&lt;code class=&quot;language-text&quot;&gt;&quot;&quot;&lt;/code&gt;取代&lt;code class=&quot;language-text&quot;&gt;text.lower()&lt;/code&gt;中所有非小写字母的字符后的字符串，相当于只保留小写字母的&lt;code class=&quot;language-text&quot;&gt;text.lower&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Counter(re.sub(&apos;[^a-z]&apos;, &apos;&apos;, text.lower()))&lt;/code&gt; 是一个 Counter() 对象（同时也是一个 dict 对象）。&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;list(Counter(re.sub(&apos;[^a-z]&apos;, &apos;&apos;, text.lower())).items())&lt;/code&gt;是一个形如&lt;code class=&quot;language-text&quot;&gt;[(&quot;a&quot;,1),(&quot;b&quot;,2)]&lt;/code&gt;的列表。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再关注&lt;code class=&quot;language-text&quot;&gt;sorted()&lt;/code&gt;的第二个参数，&lt;code class=&quot;language-text&quot;&gt;key = lambda v: (-v[1], v[0])&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;不得不说，这是一个很巧妙的设计。&lt;/p&gt;
&lt;p&gt;其返回值是&lt;code class=&quot;language-text&quot;&gt;(-v[1], v[0])&lt;/code&gt;，形如&lt;code class=&quot;language-text&quot;&gt;(-1,&quot;a&quot;)&lt;/code&gt;，这使得在排序时首先根据字符出现次数降序排序，其次根据字符的 ASCII 升序排序。恰如题目所要求。&lt;/p&gt;
&lt;p&gt;至此，不难理解这段程序的原理了。&lt;/p&gt;
&lt;h3 id=&quot;5-一行代码的解法&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-%E4%B8%80%E8%A1%8C%E4%BB%A3%E7%A0%81%E7%9A%84%E8%A7%A3%E6%B3%95&quot; aria-label=&quot;5 一行代码的解法 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;5. &lt;a href=&quot;https://py.checkio.org/mission/most-wanted-letter/publications/veky/python-3/shortest/?ordering=most_voted&amp;#x26;filtering=choice&quot;&gt;一行代码的解法&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;一行代码可以解决的问题，何必用两行？——鲁迅&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;checkio&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;97&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lower&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这种解法其实和解法 2 十分相似，唯一的不同在于用&lt;code class=&quot;language-text&quot;&gt;map(chr,range(97,123))&lt;/code&gt;取代了&lt;code class=&quot;language-text&quot;&gt;string.ascii_lowercase&lt;/code&gt;，从而减少了额外的&lt;code class=&quot;language-text&quot;&gt;import&lt;/code&gt;和代码量。&lt;/p&gt;
&lt;p&gt;关于** map 函数**，其文档如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;map(func, *iterables) —&gt; map object&lt;/p&gt;
&lt;p&gt;Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;所以&lt;code class=&quot;language-text&quot;&gt;map(chr,range(97,123))&lt;/code&gt;得到了一个相当于&lt;code class=&quot;language-text&quot;&gt;string.ascii_lowercase&lt;/code&gt;的** map 对象**，由于它同样** Iterable**，所以 max 函数可以以它为参数。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;以上，便是** CheckiO 探险日志-&gt;Home-&gt;The Most Wanted Letter **的全部内容。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[十七岁时，我们都渴望一辆单车]]></title><description><![CDATA[本文是电影《十七岁的单车》的观后感。]]></description><link>https://www.zackwu.com/posts/2017-11-10-bike-at-the-age-of-seventeen/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2017-11-10-bike-at-the-age-of-seventeen/</guid><pubDate>Fri, 10 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;本文是电影《十七岁的单车》的观后感。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-e086e0076a2294a6.webp&quot; alt=&quot;《十七岁的单车》电影海报&quot;&gt;&lt;/p&gt;
&lt;p&gt;周五之夜，按照惯常是我每周的观影时间。&lt;/p&gt;
&lt;p&gt;手边有一盒新鲜山楂，看这部电影时，不时拿起一个放入嘴里。新鲜山楂很酸，甚至有点逼出我的眼泪的倾向。所以，以下感想很可能是出于山楂的效果，不仅仅是这部电影。&lt;/p&gt;
&lt;p&gt;其实今年的我，也不过十八岁而已。狭义的十七岁，不过是我昨天的事情。&lt;/p&gt;
&lt;p&gt;有人说回忆比现实更伤感，其实我不同意，因为生活已经足够伤感了。如果觉得不够，建议吃几个山楂。那样肯定够了。&lt;/p&gt;
&lt;h2 id=&quot;十七岁是一个容易被忽视的年龄&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8D%81%E4%B8%83%E5%B2%81%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AE%B9%E6%98%93%E8%A2%AB%E5%BF%BD%E8%A7%86%E7%9A%84%E5%B9%B4%E9%BE%84&quot; aria-label=&quot;十七岁是一个容易被忽视的年龄 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;十七岁，是一个容易被忽视的年龄&lt;/h2&gt;
&lt;p&gt;古人把女子十三四岁称作豆蔻年华，十五岁及笄，十六岁碧玉年华，尔后二十，桃李年华；而男子，十五志学，二十弱冠。&lt;/p&gt;
&lt;p&gt;直到现在，人们提起年龄，十五六岁给人青少年的感受，而十八岁则是成年，&lt;strong&gt;单单少了中间的十七岁&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;十七岁，成年的前夜。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果成年是一种节日，就像圣诞、新年，那么它的前夜应该比节日当天更为珍视。可是，我们甚至忽略了十七岁。&lt;/p&gt;
&lt;p&gt;因为被忽视，因为被错过，十七岁让一切混乱有可能发生，也让所有积攒的能量有可能爆发。&lt;/p&gt;
&lt;h2 id=&quot;单车在被忽视中所寻找的存在感&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8D%95%E8%BD%A6%E5%9C%A8%E8%A2%AB%E5%BF%BD%E8%A7%86%E4%B8%AD%E6%89%80%E5%AF%BB%E6%89%BE%E7%9A%84%E5%AD%98%E5%9C%A8%E6%84%9F&quot; aria-label=&quot;单车在被忽视中所寻找的存在感 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;单车，在被忽视中所寻找的存在感&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-115e0e9af7628f18.webp&quot; alt=&quot;两人共同的单车&quot;&gt;&lt;/p&gt;
&lt;p&gt;如果正处于一个躁动的年龄，而未能得到与之相匹的注视，那么，就搞出点动静来吧。&lt;/p&gt;
&lt;p&gt;《十七岁的单车》中，两位男主人公分别是来自农村的“北漂”，北京底层的“土著”。&lt;strong&gt;他们好像截然不同，又好像同病相怜&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;“北漂”小贵，渴望融入北京这座城市，可是，他又有什么能力做到呢？他只能是一个快递员，骑着自行车穿行于北京的街巷中，成为新时代的“骆驼祥子”。&lt;/p&gt;
&lt;p&gt;在北京城，他是平淡的，甚至低人一等的。&lt;/p&gt;
&lt;p&gt;所以，他必须拥有一辆单车，这意味着他有了自己的“资产”，在这个城市有了立足之本。&lt;/p&gt;
&lt;p&gt;“土著”小坚，相比于小贵，他是一个“骄傲”的北京人：穿上学校的白衬衫、黑西装，打上红色领带，踩着一双皮鞋，神气十足。可是，他的心理需求，却一直没有得到满足。&lt;/p&gt;
&lt;p&gt;新来的妹妹比他更受继母和亲父的重视，父亲许诺购买的自行车一再拖延，这些让他在那群光鲜亮丽的哥们面前有所赧颜。&lt;/p&gt;
&lt;p&gt;他渴望一辆单车，因为只有有了单车，他才能和哥们一起去玩车，才能和心怡的漂亮姑娘潇潇一起上下学。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-7310795b3bb2a778.webp&quot; alt=&quot;潇潇（高圆圆饰）&quot;&gt;&lt;/p&gt;
&lt;p&gt;因此，单车成为了&lt;strong&gt;两人共同寻找的一种存在感&lt;/strong&gt;，唯一不同的是：对于小贵，单车的物质意义更强烈；对于小坚，单车的心理需求更重要。&lt;/p&gt;
&lt;h2 id=&quot;当我们捍卫单车时我们在想些什么&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%BD%93%E6%88%91%E4%BB%AC%E6%8D%8D%E5%8D%AB%E5%8D%95%E8%BD%A6%E6%97%B6%E6%88%91%E4%BB%AC%E5%9C%A8%E6%83%B3%E4%BA%9B%E4%BB%80%E4%B9%88&quot; aria-label=&quot;当我们捍卫单车时我们在想些什么 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;当我们捍卫单车时，我们在想些什么&lt;/h2&gt;
&lt;p&gt;电影中，非常巧合，小贵的单车被偷了，然后小坚用从家里偷来的钱从二手车市场中买来了这辆车。&lt;/p&gt;
&lt;p&gt;显然，一辆单车在一个确定的时刻确定的地点，只能被一个人拥有。&lt;/p&gt;
&lt;p&gt;而在捍卫单车时，小贵和小坚采取了完全不同的方式。&lt;/p&gt;
&lt;p&gt;小贵很“轴”，一声不吭地死死攥住单车不肯松手；小坚很“痞”，叫上一群哥们围追堵截，甚至大打出手，想要抢回单车。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可事实上，十七岁的我们，既会“轴”，也会“痞”。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;还记得吗，当年为了一部手机、一台电脑向父母软磨硬泡，苦苦哀求？还记得吗，当年为了追女神每天问候早安晚安，等着不期而遇？还记得吗，当年又是谁溜出教室为所欲为？&lt;/p&gt;
&lt;p&gt;单车，单车。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;十七岁，认定了单车，就不愿放手，甚至不需要思考什么。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-6316eb54a9c1cda8.webp&quot; alt=&quot;影片结尾，小贵扛着单车穿过街巷&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;可是又有谁能最终拥有单车&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8F%AF%E6%98%AF%E5%8F%88%E6%9C%89%E8%B0%81%E8%83%BD%E6%9C%80%E7%BB%88%E6%8B%A5%E6%9C%89%E5%8D%95%E8%BD%A6&quot; aria-label=&quot;可是又有谁能最终拥有单车 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;可是，又有谁能最终拥有单车&lt;/h2&gt;
&lt;p&gt;当然，我们都有短暂的拥有。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-c9f70d7351f1205b.webp&quot; alt=&quot;小坚与潇潇&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-8bbd04f9bfcddb64.webp&quot; alt=&quot;这个动作很危险，小朋友不要模仿！&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/8817191-e7366b04d10c2fab.webp&quot; alt=&quot;得到单车的小贵&quot;&gt;&lt;/p&gt;
&lt;p&gt;可是，十七岁的时候，又有什么能力去永远地捍卫单车？&lt;/p&gt;
&lt;p&gt;**美好易碎，龟玉毁于椟。**潇潇不再喜欢小坚，她有了新男友；快递公司会开除丢失单车的小贵。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;十七岁的单车，终归不属于十七岁的我们。&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GBK or UTF-8? Windows 平台 Python3 读写文件]]></title><description><![CDATA[在 Windows 10 平台上编写一个 Python3 程序时，出现了编码问题]]></description><link>https://www.zackwu.com/posts/2017-11-08-gbk-or-utf8/</link><guid isPermaLink="false">https://www.zackwu.com/posts/2017-11-08-gbk-or-utf8/</guid><pubDate>Wed, 08 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;想不到，我在简书&lt;strong&gt;正式&lt;/strong&gt;写的第一篇文章，居然是关于代码的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;问题&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E9%97%AE%E9%A2%98&quot; aria-label=&quot;问题 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;问题&lt;/h2&gt;
&lt;p&gt;昨晚，在 Windows 10 平台上编写一个 Python3 程序时，需要打开一个文件并从中读取一定内容。&lt;/p&gt;
&lt;p&gt;按照我之前的做法，无非是：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;xx.txt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  data&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然而，这一次，问题出现了：&lt;/p&gt;
&lt;p&gt;文件中含有的一个字符「½」，并不能正常显示，在 Python3 中用 print() 打印出来，显示为：「陆」。&lt;/p&gt;
&lt;p&gt;显然，出现了编码问题。&lt;/p&gt;
&lt;h2 id=&quot;何以如此&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E4%BD%95%E4%BB%A5%E5%A6%82%E6%AD%A4&quot; aria-label=&quot;何以如此 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;何以如此？&lt;/h2&gt;
&lt;p&gt;首先，由于 Windows 平台的默认编码是 GBK，而所打开的文件编码是 UTF-8，很有可能是混淆了两者编码方式，从而出错。那么，我查询了「陆」和「½」这两个字符的多种编码方式，如下：&lt;/p&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;字符&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;GBK&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;UTF-8&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Unicode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;陆&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;C2BD&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;E99986&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;9646&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;½&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;无&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;C2BD&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;BD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以发现，「½」的 UTF-8 编码和「陆」的 GBK 编码结果一致。&lt;/p&gt;
&lt;p&gt;这也就解释了为什么「½」会变成「陆」：文件中「½」的 UTF-8 编码被错误地当作 GBK 编码来解释，从而产生了「陆」。&lt;/p&gt;
&lt;p&gt;然而，为什么会这样呢？为什么文件中的其他字符并不会产生这样的错误呢？&lt;/p&gt;
&lt;p&gt;以字符「K」、「7」、「。」、「辄」为例（分别代表英文字符、数字、中文符号、中文字符）比较它们的编码：&lt;/p&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;字符&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;GBK&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;UTF-8&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Unicode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;K&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4B&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4B&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;7&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;37&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;37&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;。&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;A1A3&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;E38082&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;3002&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;辄&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;E9FC&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;E8BE84&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;8F84&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以看出，对于原生的 ASCII 字符，其 GBK 和 UTF-8 编码完全一致，所以不会产生任何问题，即便混淆了编码方式；但是对于非 ASCII 字符，如中文字符，其 GBK 编码占用 2 个字节，UTF-8 编码占用 3 个字节，且两者完全不一致，故混淆编码方式会出现错误。&lt;/p&gt;
&lt;p&gt;比如，倘若文件内容是「无辄」，按照本文开头的方式打开此文件，会变成「鏃犺緞」；倘若文件内容是「辄」，则会抛出 &lt;code class=&quot;language-text&quot;&gt;UnicodeDecodeError&lt;/code&gt; 错误。&lt;/p&gt;
&lt;p&gt;原因很简单，「无辄」的 UTF-8 编码结果有 6 个字节，被错误地解释为 3 个 GBK 编码的字符；而「辄」仅 3 个字节，无法按照 GBK 编码理解，因此直接报错。&lt;/p&gt;
&lt;p&gt;而「½」更为特殊的是，不同于一般的中文字符，它的 UTF-8 编码是 2 个字节，因此被错误地用 GBK 打开时并不会报错。&lt;/p&gt;
&lt;h2 id=&quot;如何解决&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3&quot; aria-label=&quot;如何解决 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;如何解决？&lt;/h2&gt;
&lt;p&gt;不妨先查阅一下 Python3 中关于 open() 函数的说明，在 Python 交互界面中输入：&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;结果如下（已省略无关内容）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Help on built-in function open in module io:&lt;/p&gt;
&lt;p&gt;open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)&lt;/p&gt;
&lt;p&gt;encoding is the name of the encoding used to decode or encode the
file. This should only be used in text mode. &lt;strong&gt;The default encoding is
platform dependent&lt;/strong&gt;, but any encoding supported by Python can be
passed. See the codecs module for the list of supported encodings.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;注意加粗部分，在不指定 encoding 参数时，open() 函数默认采用和系统相关的编码方式。而在 Windows 系统下，系统相关的编码方式是 GBK，不是 UTF-8。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这便是产生错误的根源。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;那么，解决方法也很简单，只需要指定 &lt;code class=&quot;language-text&quot;&gt;encoding=&quot;utf8&quot;&lt;/code&gt; 即可。&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;xx.txt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;encoding&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;utf8&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  data&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;从此天下太平。&lt;/p&gt;
&lt;h2 id=&quot;反思&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%E5%8F%8D%E6%80%9D&quot; aria-label=&quot;反思 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;反思&lt;/h2&gt;
&lt;p&gt;虽然 Python3 中的 &lt;code class=&quot;language-text&quot;&gt;str&lt;/code&gt; 采用 Unicode 编码方式，相比于 Python2 对于中文的支持有了很大的提升，但为了尽可能地减少麻烦，在涉及到中文或其他非 ASCII 字符时，务必记得设定编码方式为 UTF-8。&lt;/p&gt;
&lt;p&gt;尤其是在 Windows 平台。&lt;/p&gt;</content:encoded></item></channel></rss>