2022 · 起点
今天是 2022 年的最后一天。
广州的冬天总是带着一点潮湿的冷意,风从阳台半掩的玻璃门缝隙里钻进来,吹在敲键盘的手背上。宿舍里没开大灯,只有屏幕的光打在脸上。外面隐隐约约有零星的鞭炮声,大概是附近村落里的人在提前庆祝新年。室友们都出去跨年了,桌上的外卖盒还没来得及扔,空气里混杂着一点冷掉的烧鸭饭的味道。
我一个人坐在椅子上,面前开着一个空的 VS Code 窗口。光标在第一行匀速地闪烁,像某种平缓的呼吸。倒了一杯温水,水汽在杯口打着旋散开。突然觉得,在这样一个时间节点,应该写点什么,把过去这几个月大一刚入学的痕迹固化下来。
九月,入学。
从老家到广州的火车开了很久。硬座车厢里的气味很混杂,窗外的风景从平原变成丘陵,再变成密集的南方建筑群。行李箱很重,里面装着衣服、几本书,还有一台从亲戚那里接手的二手联想笔记本电脑。开机的时候,机械硬盘会发出细碎的咔哒声,散热风扇随之发出类似拖拉机启动的轰鸣,键盘的几个键帽已经磨得发油,尤其是 WASD 和回车键,反着一点微弱的光。
广州商学院。把行李搬进宿舍的那天,我站在阳台上看了一会儿楼下的校道。这里没有百年名校的参天古木,也没有自带光环的学术氛围。这只是一所普通的民办本科,一个被很多人称为三本的地方。在很多社交平台上,这种学校的标签往往和“混日子”、“找不到工作”绑定在一起。
但我没什么落差感,反而觉得平静。高考的数字已经是既定事实,懊悔或者自怨自艾都是一种情绪上的内耗。环境已经是这样了,接下来能改变的,只有自己每天坐在桌前的时间。
十月,开始真正接触计算机的世界。
第一次知道 Git 这个东西,是在物联网实验室的招新考核上。在那之前,我以为代码只能装在 U 盘里拷来拷去,或者把文件夹压缩打包,命名为“最终版”、“绝对最终版”、“打死不改版”。跟着网上的教程,在终端里敲下 git init,然后是 git add . 和 git commit。看着绿色的字符在黑色的背景里跳动,虽然还不太懂什么叫版本控制,但觉得这种和机器对话的方式很纯粹。当然,第一次用 Git 的时候我也卡在了 Vim 编辑器里,不知道怎么退出,最后只能强行关掉终端窗口重新打开。
后来用学生优惠买了一台腾讯云的轻量应用服务器,装了 CentOS 系统。第一次用 SSH 连上服务器的时候,看着那个带有 root 权限的命令提示符,有一种握住了某种权力的错觉。我照着博客,笨拙地敲着 Linux 命令,一步步装上了 Nginx。修改配置文件的过程很不顺利,因为漏掉了一个分号,Nginx 死活启动不起来,查日志查了半个多小时。等终于把写好的静态 HTML 页面传上去,在手机浏览器里输入那个公网 IP,看到自己写的页面加载出来时,我在椅子上愣了很久。
那是第一次,我写的东西脱离了这台破旧的笔记本,存在于互联网的某个角落。任何人只要输入这串数字,就能看到我创造的界面。
在这个月,我加入了物联网实验室。实验室在实训楼,推开门总能闻到一股淡淡的松香和电烙铁的味道。里面有很多比我厉害的人,他们屏幕上的代码密密麻麻,看文档的速度比我翻书还快。我找了个靠窗的角落坐下,开始了我漫长的补拙过程。
十一月,开始学 Java。
在 B 站找了播放量最高的教程,一节一节地跟。那段时间,耳机里永远是视频里老师敲键盘的声音和略带口音的讲解。
学编程的过程并不像电影里演的那样,黑客的手指在键盘上飞舞,然后屏幕上出现华丽的界面。更多的时候是极其枯燥和琐碎的。配置环境变量 JAVA_HOME 就卡了我一整个下午,因为路径里多了一个不起眼的空格,命令行里死活认不出 javac 命令。听到面向对象、多态、接口的时候,脑子里是一团浆糊。我不理解为什么要把简单的事情搞得那么复杂,为什么要写那么多 getter 和 setter。
听不懂,就暂停。把进度条往回拉,再听一遍。有时候室友在背后打游戏,机械键盘敲得劈啪作响,语音里喊着推进和撤退,偶尔伴随着几句情绪激动的脏话。我戴着降噪耳机,看着屏幕上死活跑不通的 NullPointerException,会有一种巨大的孤独感。空指针异常是这个世界上最诚实的东西,它不关心你的情绪,它只是冷冰冰地告诉你,你以为存在的东西,其实并不存在。
但把报错信息复制到搜索引擎,在 Stack Overflow 上找到相似的问题,往下翻看高赞回答,修改代码,重新编译,看到控制台输出 Process finished with exit code 0 的那一刻,那种平静的愉悦感,足以抵消之前所有的烦躁。
十二月,期末周。
大学的压强在年底第一次向我展现了它的全貌。C 语言的期末考试里那些绕来绕去的指针、高数的微积分复习、实验室的期末考核项目,还有各种需要提交的总结报告,全部叠在一起压了下来。
那段时间,每天早上七点半去图书馆,晚上十点半闭馆才出来。广州的十二月偶尔会下冷雨,走在回宿舍的路上,路灯把树叶的影子拉得很长。物理上很疲惫,每天喝两杯劣质的速溶咖啡续命,但奇怪的是,精神上却有一种很真实的充实感。没有时间去迷茫,每天的任务清单都在推动着我往前走。
这几个月,学的东西很杂,也很浅。
HTML 和 CSS 让我对网页有了基本的认知。JavaScript 基础让我知道页面是怎么动起来的。Java 入门让我习惯了强类型语言的严谨和繁琐。Linux 的基本命令让我在没有图形界面的环境下不再恐慌。
动手做了两个小东西。
一个是用纯 Servlet 和 JSP 写的留言板。没有用任何框架,连数据库连接都是用最原始的 JDBC 一行一行敲出来的。它能跑,但是极其丑陋。为了把一个 div 居中,我查了半个小时的 CSS 属性,最后发现是因为 display 属性没设置对,只能用了最笨的 margin 负值法。在处理用户输入的时候,没有做任何防注入。后来自己试着在留言框里输入了一段包含 alert(1) 的 <script> 标签,提交之后,发现整个页面直接弹出了警告框,原本的布局也崩溃了。这是我第一次直观地感受到什么是 XSS 攻击,也是第一次意识到,永远不要信任用户的输入。
另一个是一个简单的课表小程序,算是个半成品。想尝试去解析教务处的课表接口,自己做个好看一点的课表 UI。但遇到了跨域请求的问题,浏览器控制台里一片红色的 CORS 报错。接着是复杂的 Token 验证和加密算法,用 Fiddler 抓包抓了几天也没搞明白学校的登录逻辑。最后妥协了,把课表数据手动写死在了 JSON 文件里,通过本地读取来渲染页面。虽然有点挫败,但也让我明白,工程很多时候就是和现实妥协的艺术。在能力不足的时候,先让它跑起来,再谈其他。
踩了很多坑。用 Git 的时候不小心进入了 Detached HEAD 状态,写了一下午的代码 commit 之后发现分支不见了,以为代码全丢了,吓得一身冷汗。最后查了很久的文档,通过 git reflog 找到提交的哈希值,才把记录找了回来。写 Java 的时候,因为没有重写 equals 方法,导致两个内容完全相同的字符串用 == 比较时返回了 false。我不理解为什么有时候 == 是管用的,有时候又不行。这个 Bug 我查了一整个晚上,直到看到了关于 Java 字符串常量池和堆内存分配的文章,才恍然大悟。
但坑里有时候真的会找到宝藏。每一次排错,都是对底层原理的一次反向摸索。慢慢地,我不再那么害怕报错了。大片的红色错误堆栈不再是阻碍,而是一种反馈,它在诚实地告诉我,我的逻辑在哪里出现了断层。
大学和高中不同,人与人之间的交集变得很随机。
认识了一些人。有些在做完小组作业后就再也没有说过话,变成了微信列表里一个不会闪烁的头像,只是点头之交。有些则因为经常在实验室一起熬夜,变成了会分享外卖链接和技术博客的朋友。
十二月中旬的一个晚上,实验室里只剩下我和一个大三的师兄。他在调一个单片机的驱动,桌上堆满了杜邦线和裸露的电路板。我在死磕我的留言板,试图把 JDBC 的连接写成一个单例模式。
我停下敲键盘的手,转过头问他,我们这种民办三本的学生,出去找工作是不是很难。简历是不是连机器筛选那一关都过不去。
他停下手里的动作,转过椅子看着我。他没有说那些假大空的鸡汤,也没有抱怨大环境的寒冬。他只是很平静地说了一句话:
「技术是可以学的,网上的教程到处都是。但执行力才是差距所在。很多人只是在想,在焦虑,而我们必须去做。」
这句话我记下来了,写在备忘录的置顶里。
也是在那个月,实验室发了蓝桥杯和 ACM 选拔的通知。我报了名,开始在 LeetCode 上刷题。第一题是 Two Sum,我用两层 for 循环的暴力解法跑通了,耗时几十毫秒。但在看题解的时候,发现用哈希表可以把时间复杂度降到 。那是另一种维度的震撼。相比于写业务代码时堆叠的 API,算法更像是数学和逻辑的纯粹结合。
那台二手联想电脑在跑带递归的测试用例时,风扇转得更响了。有时候一个数组越界的 ArrayIndexOutOfBoundsException 会卡我好几个小时,我在草稿纸上画满了一个个方框,模拟指针的移动
