创作1024天:在代码与实验里记录我的技术成长路

机缘

最初开始写技术博客,其实没有复杂的想法,纯粹是为了“搞定自己的学习”。

大二上C语言课时,第一次写《空心数字金字塔》代码,调试了半节课才理清循环逻辑,当时怕下次忘记,就把思路和易错点记在笔记本上。后来发现班里不少同学也卡在同样的地方,我把笔记整理成图文版发在CSDN,没想到帮到了好几个同学——这是我第一次觉得“把自己的学习记录分享出去”是有价值的。

真正让我坚持下来的,是实战实验中的“踩坑经历”。做Upload-Labs靶场时,从第5关的MIME校验绕过,到第17关的条件竞争,每一关都卡了很久,查了很多资料才解决。当时想:“要是有人能把这些坑和解决方法整理好,我也不用走这么多弯路”,于是干脆自己动手写了《Upload-Labs靶场全20关通关攻略》,从环境配置到原理分析,把每一步的报错截图和解决代码都贴上去。这篇博文后来成了我阅读量最高的文章之一,甚至有其他学校的同学私信说“靠这篇攻略过了课程设计”,那一刻突然觉得,创作不只是记录,更是在帮别人少走自己走过的弯路。

再后来,学Java、Spring AI、Linux时,我习惯性地把实验报告“升级”成博文:做完华为eNSP的VLAN配置实验,就整理成《跨交换机VLAN配置实践》;开发PHP员工管理系统时,把数据库设计、CRUD代码、SQL注入防护写成详细教程;就连帮同学解决Python zxing库报错、C++回文素数编程题时,也会把解决过程写成问答笔记——慢慢的,创作就成了我学习的“固定环节”。

收获

这1024天的创作,比我想象中收获更多“小确幸”。

数据上不算惊艳,但每一个数字都很踏实:累计写了30多篇博文,其中《【c语言】空心数字金字塔》有4716次阅读,《基于微信小程序的在线聊天功能实现》有3382次阅读;收到了300多个点赞和200多份收藏,最意外的是《Upload-Labs靶场攻略》被19位网友收藏,有人评论说“帮我搞定了渗透测试课程的期末作业”,每次看到这样的反馈,都觉得比考了高分还开心。

更珍贵的是认识了一群“技术搭子”:有个网友因为看了我写的《Spring AI集成Ollama指南》,私信问我配置时的端口问题,后来我们经常一起讨论AI模型部署;班里有同学跟着我的《Linux权限管理详解》复习,期末前还拉着我一起梳理重点;甚至有位学长看到我写的《微信小程序登录全流程》,推荐我加入了学校的技术社团——这些因分享而产生的连接,让我不再是一个人闷头学技术。

还有一个意外收获是“倒逼自己学扎实”。写《Markdown从零到精通》系列时,为了讲清楚数学公式和图表绘制,我特意去查了KaTeX和Mermaid的官方文档,原本模糊的知识点变得清晰;写《PHP与MySQL实战》时,为了确保代码安全,反复验证预处理语句防SQL注入的效果——原来“要把知识讲给别人听”,才是检验自己是否真懂的最好方式。

日常

对我来说,创作从来不是“额外任务”,而是和上课、实验绑定在一起的“学习闭环”。

平时上课记的笔记比较零散,课后整理实验报告时,我会把重点提炼成博文框架:比如做完华为eNSP的DHCP配置实验,趁热把“租期管理”“冲突检测”的步骤和配置代码写成草稿,晚上回宿舍再补充截图和原理说明;周末没课的时候,会集中处理“系列内容”,比如《Linux命令详解》系列,每周写1-2篇,从基础命令到文本处理,慢慢攒成体系。

平衡学习和创作的秘诀,就是“不贪多、靠碎片”。上课前的10分钟,我会在手机上列好当天要写的博文大纲;实验间隙的空闲时间,用手机拍下游标卡尺的配置截图或代码报错界面;甚至在食堂排队时,会在备忘录里写好博文的引言——这样既不耽误课程作业,也能慢慢积累内容。

偶尔也会有“不想写”的时候,比如期末周要复习考试,就暂时停更;遇到复杂的技术点(比如Spring AI的函数调用),卡了一周没理清,就先把疑问记下来,等搞懂了再补写成文。对我来说,创作不是“完成KPI”,而是“记录自己的成长节奏”,这样反而能坚持得更久。

成就

如果说过去写过最有成就感的代码,应该是《基于微信小程序的在线聊天功能实现》里的WebSocket通信核心代码。当时做这个课程设计时,卡在“实时消息同步”和“断线重连”上很久,最终实现的代码不仅完成了课程要求,还被不少网友参考,这也是我阅读量最高的博文之一。

// 微信小程序端 - WebSocket核心逻辑(app.js)
App({
  globalData: {
    socketOpen: false,
    socketMsgQueue: [],
    userInfo: null // 存储当前用户信息
  },

  // 初始化WebSocket连接
  initWebSocket() {
    const that = this;
    // 连接后端WebSocket服务(替换为实际后端地址)
    wx.connectSocket({
      url: 'wss://your-server-domain/ws/chat',
      header: {
        'content-type': 'application/json'
      },
      success(res) {
        console.log('WebSocket连接发起成功', res);
      }
    });

    // 监听连接打开
    wx.onSocketOpen(function(res) {
      that.globalData.socketOpen = true;
      console.log('WebSocket连接已打开');
      // 发送队列中缓存的消息
      if (that.globalData.socketMsgQueue.length > 0) {
        for (let msg of that.globalData.socketMsgQueue) {
          that.sendSocketMessage(msg);
        }
        that.globalData.socketMsgQueue = [];
      }
    });

    // 监听消息接收
    wx.onSocketMessage(function(res) {
      const msgData = JSON.parse(res.data);
      // 触发全局消息事件,让页面接收消息
      wx.$emit('onSocketMsg', msgData);
    });

    // 监听连接关闭
    wx.onSocketClose(function(res) {
      that.globalData.socketOpen = false;
      console.log('WebSocket连接已关闭,5秒后重试...');
      // 断线重连(避免频繁重试)
      setTimeout(() => {
        that.initWebSocket();
      }, 5000);
    });

    // 监听连接错误
    wx.onSocketError(function(res) {
      console.error('WebSocket连接错误', res);
      that.globalData.socketOpen = false;
    });
  },

  // 发送WebSocket消息(处理连接未打开时的缓存)
  sendSocketMessage(msg) {
    if (this.globalData.socketOpen) {
      wx.sendSocketMessage({
        data: JSON.stringify(msg)
      });
    } else {
      this.globalData.socketMsgQueue.push(msg);
    }
  },

  onLaunch() {
    // 登录后初始化WebSocket
    wx.getStorage({
      key: 'userToken',
      success: (res) => {
        this.globalData.userInfo = { token: res.data };
        this.initWebSocket(); // 登录成功后建立连接
      }
    });

    // 全局事件总线(用于页面接收消息)
    wx.$emit = function(eventName, data) {
      wx.$events = wx.$events || {};
      if (wx.$events[eventName]) {
        wx.$events[eventName].forEach(callback => callback(data));
      }
    };
    wx.$on = function(eventName, callback) {
      wx.$events = wx.$events || {};
      wx.$events[eventName] = wx.$events[eventName] || [];
      wx.$events[eventName].push(callback);
    };
  }
});

这段代码解决了三个核心问题:一是通过“消息队列”处理WebSocket连接未打开时的消息缓存,避免消息丢失;二是实现断线自动重连(5秒重试一次,平衡性能和可靠性);三是用全局事件总线让多个页面能接收消息,比如聊天页面、消息通知页面都能实时获取新消息。当时做完后,不仅顺利通过了课程设计答辩,还帮班里另外两个同学解决了类似的实时通信问题——这大概是“代码+分享”带来的双重成就感。

憧憬

作为还在上学的技术学习者,未来的创作和成长,还是想围绕“学习”和“实用”两个关键词展开。

学习上,计划把现有的技术系列补完整:比如《Spring AI实战系列》只写了5篇,接下来想补充“RAG检索增强”“多模态模型集成”的内容;渗透测试方向,打算继续更新其他靶场(如DVWA、SQLi-Labs)的通关攻略,配合课程里的网络安全知识,形成更系统的笔记;另外,还想增加“课程实验”相关的内容,比如计算机组成原理的组合逻辑电路设计、操作系统的进程调度模拟,帮自己复习的同时,也给低年级同学提供参考。

创作上,想尝试更“轻量”的分享形式:比如把Linux常用命令、MySQL语法整理成“速查表”博文,方便大家快速查阅;偶尔在班级群或社团里做小分享,比如“10分钟学会用Markdown画流程图”“Spring Boot项目避坑技巧”,把博文里的内容转化成更直观的口头分享,锻炼自己的表达能力。

长远来看,希望毕业后能从事Java开发或安全相关的工作,而这些博文会成为我的“技术简历”——每一篇都是我学习的见证,每一段代码都是我实战的积累。1024天只是开始,未来还想继续在“学习-实践-记录”的循环里,慢慢成为更扎实的技术人。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐