<?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[CorrectRoad's Blog]]></title><description><![CDATA[时来天地皆同力，运去英雄不自由。]]></description><link>https://blog.778917.xyz</link><generator>Yohaku (https://github.com/Innei/Yohaku)</generator><lastBuildDate>Wed, 13 May 2026 19:59:23 GMT</lastBuildDate><atom:link href="https://blog.778917.xyz/feed" rel="self" type="application/rss+xml"/><pubDate>Wed, 13 May 2026 19:59:23 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[IT基建与 AI]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/tech/it-infra-and-ai">https://blog.778917.xyz/posts/tech/it-infra-and-ai</a></blockquote><div><p>最近计划重构博客。之前那个博客的模板<a href="https://github.com/saicaca/fuwari">fuwari</a>有一些问题，因为不支持友链(导致没有办法与别人博客做DR)，作者也长年不更新了。所以这次迁移到 Innei 的 Mix Space 机制。因为内容与代码分离，所以 follow 上流更新也更容易了。</p><p>对于今天开始薅 Oracle Cloud 的服务器，没有想到一次就拿下 4C24G 的 ARM 机子，而没有被 ABC，也是运气好。</p><p>我现在已经有好几台服务器了，如果再加一台 Oracle Cloud 在过去运维起来很麻烦，但是好在我构建了一个很好的 AI Native 的 IT Infra，今天非常轻松就把服务器并入管理并配置上面的应用。下面简单介绍一下我家的IT基建与拓扑。</p>
<p>原则: 通过声明式、GitOps让整个 IT 基建能被 AI 理解、管理、迭代。</p><p>系统层 NixOS</p><p>网络层 Tailscale</p><p>应用层 K3s + ArgoCD</p><h1 id="">网络</h1><p>网络主要需要解决几个问题，一个家里设备无缝上网与翻墙。另一个是安全的内网访问。构建以下网络拓扑。</p>
<p>// SVG图，</p><h1 id="">应用</h1><p>应用主要是通过内网提供服务，特意避开了公网。因为主要是出于安全考虑。现在AI时代安全漏洞越来截止容易被发现与利用。被1day漏洞是防不胜防。所以最好的方案只能是所有的服务都放在内网。依靠带隔离提供安全性。</p><p>然后通过tailscale提供https服务功能。通过<code>服务名.域名</code>来访问。</p><p>我的应用</p><p>Uptime、Grafana。前者监控所有的其中后者用于做 PG、各种线上服务的监测。</p><h1 id="">备份</h1><p>应用有两种，一种是stateless，无PVC持久化的。状态保存在Postgre与有PVC的。前者的Postgres使用PGBackRest。后者使用k8up来统一备份到一个目标。</p><p>然后通过该目标再备份到隔地Nas与R2 来实现3-2-1的备份。</p><h1 id="">自动修复问题</h1><p>配置了Uptime，监控所有的应用，然后当有服务出现意外在重试之后依然不行的就自动通过web触发 AI Agent进行自动修复。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/tech/it-infra-and-ai#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/tech/it-infra-and-ai</link><guid isPermaLink="true">https://blog.778917.xyz/posts/tech/it-infra-and-ai</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Tue, 21 Apr 2026 13:46:52 GMT</pubDate></item><item><title><![CDATA[2025年终总结]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/life/2025">https://blog.778917.xyz/posts/life/2025</a></blockquote><div><h2 id="">年终总结</h2><p>赶在 2025 的最后一天在这里写年终总结。写下这行的时候离 25 年结束还有 8 个小时，希望能赶的上。今年居然连一篇博客没有更新，其实我每天的文字输出很多，能有很多有意思的点子，现在还有好几篇在 Draft 的 Blog。但是写一篇完整 Blog 的启动阻力真的好大。所以一直没有完成。</p><p>今年其实不是很顺利，甚至可以说是绝大部分的事都不如意，但是正如『少有人走的路』中开篇所讲『人生本就困难重重』，我认为这个应该能有一个美妙的数字方式来证明这件事，但是这里空白太小了，写不下🤣。</p><p>不过今年的工作事业运还行，成功拿到了 30+W 年包的 Offer 回了老家福州。也不用再负担上海那贵的心疼的房租。所以整体比较宽裕，一改之前低物欲的性格，买了好多挺贵的家具还有电子产品，回头可以写一篇好物推荐，真的很能满足情绪价值😘。</p><h2 id="">副业</h2><p>今年多了一个关系很好的朋友。上半年在冰鲸的时候，发现和设计师 Leo 我们两个人很像也很合拍，每天都聊很多。在我离职之后，还一起合作做一个小软件。先是通过 Google Search 验证了搜索量，存在这个需求。其实我们根本没有想到这个能挣到钱，不过现在看起来居然有千把块的进账，虽然和工资相比还是微不足道，还是很让人开心的。</p><p>今年成长了好多，读了好多书，听了好多播客。产出是比之前少的，做了很多 Demo，得已于 AI。在不断学习与摸清 AI 的能力边际。我依然不认为 LLM 会完全替代人类，也觉得 AICG 不会很快就来。未来几年对于基本功与知识的广度应该会越来越重要。</p><p>我今年主要是扩展了非本职行业以外的知识与技能，有原理也有一些小技巧。像需求的验证，Marketing还有运营甚至产品设计都感觉有些心得与经验了。这块真的很有意思，但是大部分都是零碎的点，比如适合发微博。或许我继续把我的 X 账号给继续运营起来。</p><h2 id="">最近做的有意思的事</h2><h3 id="ai-it-infra">AI IT Infra</h3><p>今年最大的事就是 AI 与 Agent 的大进步了。最近重整自己的 IT 基建的时候感觉范式真的被改变了。</p><p>这几天我用 NixOS + k8s 重做了我家现有的 IT 基建。写了很多 Agent Skills， 让 Claude Code 来运维我家里那几台服务器、Nas还有很多台 VPS。本来运维这些设备很麻烦了、也很消耗精力，一但出问题就变成不断消耗我时间的技术债。 现在在 AI 的帮助下，已经能管理的非常好了。 特别是能做到 Configure as Code，AI 能有完整的上下文了。</p><p>我在这套 IT 基建上构建很多有意思的工作流，从信息的获取(稍后读、记录想法)、任务管理、日志、身体数据的量化。通过 n8n + Logseq 打通这一切。也得益于 Logseq 今年的 DB 更新。作为超级小白鼠也是给秦天生（tiensonqin）report 了好多 bug。等我有空了应该会把 workflow 做成一个 template 开源一下。</p><h3 id="">桌游</h3><p>今年还多了一个爱好就是玩桌游。期间还尝试过跑团，但是讲实话没那么有意思。基本每周都会去次桌游店。本来是为了 social 的，但是福州城市小就那几个人，最后真的只是大家一起快乐的玩桌游。</p><h3 id="">整理新家</h3><p>这块好多，感觉要写不完了，下次再来写吧。回头新开一篇吧。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/life/2025#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/life/2025</link><guid isPermaLink="true">https://blog.778917.xyz/posts/life/2025</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Wed, 31 Dec 2025 00:00:00 GMT</pubDate></item><item><title><![CDATA[用 AI 整理了最近六年的日记]]></title><description><![CDATA[<link rel="preload" as="image" href="https://img.778917.xyz/ai-note/diary.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/notes/6">https://blog.778917.xyz/notes/6</a></blockquote><div><p><img src="https://img.778917.xyz/ai-note/diary.png"/></p><p>从 18 年开始，我写了好多日记，但是在这六年间，我换了好几个笔记软件，从 OneNote 到 Obsidian 再到 Logseq。这些日记跨越了不同软件、不同格式。之前不敢想像能把多年的日记能聚集在一起，因为确实抽不出来时间来写软件脚本，把他们之前的差异打平。</p><p>但是最近用上 Claude 之后发现这个 AI 确实不太一样，能写出来的代码确实很 work。在一顿操作之后，用 claude 写了十几个 one off脚本，，把不同格式、来源的笔记都转换成当前使用的 logseq 的格式。</p><p><a href="ai-change-program">正如之前所提到的</a>，AI 将可能改变开发的范式，在之前写 one off 的脚本，大家都是用 Ruby，各种文件读写 API 调用的方便，写起来也是又短又快。但是在 AI 时代，这些语法糖、API带来的优势并不重要了，用 Python 反而有优势，一是语料大，二是懂的人多，用 Python 的优势大于 Ruby。</p><p>这样类似的事在 V0.dev 出来的时候我就想过，比如 Solid.js 很甜是吧，但是 React 的语料是你的数倍，用 AI 写前端，React 的质量就是会比 Solid.js 高、容易。这些后发的新语言/框架感觉更难出头了。</p><p>除非语法糖是对 AI 友好的，比如 Tailwind CSS，把 CSS 和 组件放在一起，这样 AI 写 Tailwind 就比写 SaSS 容易了。</p><p>除了对 AI 友好的编程语言会在未来脱颖而出，还有对 AI 友好的软件、内容格式也会在未来的竞争获得超乎想像的竞争优势。更容易与 AI 结合，再与其它工具联动，从而形成 1 + 1 &gt; 2 的效果。</p><p>在现在很多软件通过数据库/私有格式来存储数据，但是这种私有格式对 AI 感觉太不友好了。就拿用书籍、文章来做来 AI 的知识库，用 Markdown 的书籍远比用 PDF(更甚是图片形式的PDF)好处理的多。</p><p>用可人类理解的文件还有很多好处，比如之前读 Obsidian 作者的 <a href="https://stephango.com/file-over-app">File over app</a> 哲学，『如果你希望你的文章在 20 世纪 60 年代或 21 世纪 60 年代的电脑上仍可阅读，那么你的笔记在 20 世纪 60 年代的电脑上也能阅读』。用文件来存储数据，可以让数据活的更久。</p><p>但是同样可以看到像 Logseq、 Affine、Anytype 等等软件又转向了通过数据结构来存储数据，尽管他们也有难言之隐，比如用 Markdown 存储笔记的 Logseq 以在同步中丢失数据而出名。但是或许我们能在两者之间找到平衡点。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/notes/6#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/notes/6</link><guid isPermaLink="true">https://blog.778917.xyz/notes/6</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Sun, 22 Sep 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[我在构建一个 Indie Hacker 项目的学习与实践]]></title><description><![CDATA[<link rel="preload" as="image" href="https://img.778917.xyz/pve-client-introduction/PRD.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/tech/pve-client-introduction">https://blog.778917.xyz/posts/tech/pve-client-introduction</a></blockquote><div><h2 id="">介绍</h2><p>有好一段时间没有更新博客了，主要是因为从学校毕业之后转正的工作比较忙了。然后学习、沉淀了一段时间。最近又想开一个新的坑，与之前想到啥就做啥的 Side Project，这次我用上了学习各种 Indie Hacker 的方法。这篇文章主要还是记载一下我是怎么尝试 build 一个项目，而不是 PVE 本身和软件的介绍。</p><h2 id="build-">Build 之路</h2><p>大概一个月前开始感觉 PVE 在手机上不太好用，如果能有一个手机端的客户端就好了。再从而觉得如果只有管理感觉没有啥意思，如果再有一些很酷的功能，比如一键显卡直通、一键安装 Windows 系统等等那就更好了。</p><p>但是调研完市场之后感觉这个市场算是比较蓝海的，产品的形式还没有定义出来，像 VidHub 直接抄 Infuse Pro 就很舒服，做为一个 PVE Client，我很难说我觉得这些痛点是否是真的用户所需要的东西。 所以开始漫长的调研。</p><h2 id="">市场调研</h2><p>其实前面就是市场调研，先是调研了市面上所有的 PVE 客户端，然后是 PVE 现有的工具。这个其实没有啥价值，现有的市场很小，没有一家说能是成熟的。</p><p>首先第一步就是搞 SEO，我用了五分钟做了 Landing Page，然后部署上去，想看看能不能收集到一些 User。觉得有可能再开工，但是发现各种不太可能，当然包括我对 SEO 不太熟，官网上线谷歌和Bing之后一周之后依然没有任何流量。只能说没有搞外链啥的基本不太可能有权重。</p><p>然后开始研究 SEO，我最初的想法是比如我不清楚用户需要什么，就可以通过SEO来看看需求对应的搜索量。比如如果 PVE GPU pass-through 的搜索量很大，就说明这个功能是用户所需要的。然后我还能从中找到我想不到的各种用户需求。</p><p>但是发现这个市场实在是太小了，我用了谷歌趋势，还在淘宝上买了 Ahrefs 的工具都没有找到什么有用的信息。比如前几名是 How install PVE, 后面几位也是一些很基础的问题。根本无法定位有效的需求。</p><p>所以开始埋伏在 Reddit 和 QQ 群。然后依然发现大家的问题是非常非常的小众，很难提取出共同的需求。</p><p>在上面简单的都做完之后，一无所获的我只能开始用户调研，我用 The Mom Test 的方法开始我认识的 PVE 用户开始大量的谈话。</p><p>这一步之后我依然感觉非常痛苦，首先我没有采用引导式的对话，我都是尽可能简单的和他们聊天谈 PVE。但是从他们身上只能感觉到 PVE 用起来没有啥坑(除了Ceph)，也没有踩什么坑，现在东西也都够用的感觉。</p><p>是的，我根本没有办法从用户的聊天中得到哪怕一个他们觉得的痛点。就算我带点引导的提问，你上次搞那个硬盘直通，你感觉有坑吗? 难搞吗，他们都会说感觉不难呀，没有啥坑呀。🤔  我一度怀疑这个市场这么小，是不是就是大家根本不需要这个玩意。</p><p>但是回过头来想想或许现在存留下来的玩家都是被筛选过的，前期觉得难的用户已经消失了，所以我的调研对象的取样错了。所以在大概列出功能之后还是决定开始开发。</p><h2 id="pve-client-">PVE Client 未来大概要做什么</h2><p>大概关于 Marketing 的想法还是 SEO 先行，后续可以好好做 SEO，比如写一系列的文章，比如如何在 PVE 中显卡直通，内容就是使用我的软件一键配置 PVE 显卡直通。如何在 PVE 安装 Kail、Ubuntu、Windows。一系列文章来占领搜索引擎。</p><p>然后功能上先大概出一个 MVP，尝试拉一些早期用户起来，尽可能的通过倾听真实用户的需求，然后快速迭代来快速开发。目前最大的困难感觉就是倾听不到真实用户的需求。</p><p>比如第一个MVP中，我想给用户至少一个 ah moment。但是交付哪一个呢? 我没有提交 waitlist 用户的投票选项，也没有听到核心用户群的反应。所以在早期的 MVP 中会变得非常非常的迷茫。</p><p><img src="https://img.778917.xyz/pve-client-introduction/PRD.png"/></p><p>今天用 VitePress 把 <a href="https://pve.zeabur.app/">PVE Client</a>的 Landing Page 重构了一下。这个比我之前用的那个模块好做 Content 的 SEO 和 sitemap。</p><p>预期下周能产出一个基本能用的 MVP，希望能做完 SEO 之后能收获一些早期用户吧。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/tech/pve-client-introduction#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/tech/pve-client-introduction</link><guid isPermaLink="true">https://blog.778917.xyz/posts/tech/pve-client-introduction</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Mon, 29 Jul 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[勇敢的人会不会只是运气好?]]></title><description><![CDATA[<link rel="preload" as="image" href="https://img.778917.xyz/brave/book_cover.jpg"/><link rel="preload" as="image" href="https://img.778917.xyz/brave/summary.jpg"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/life/brave">https://blog.778917.xyz/posts/life/brave</a></blockquote><div><h2 id="">做出决策</h2><p>能挣大钱的事都是有风险的，在『美团清华产品课』中美团的王慧文说他们能成功有很大一部分原因是因为他们勇敢。</p><p>我在雷锋网读了到那些现在那些独角兽、成功的公司还有那些失败的公司的故事，其实各种调研、分析都很难说个对错，确实迈出第一步的勇敢是很重要的。</p><p>尽管现在复盘起来他们的当初的决策中会有看到各种判断、分析。从怎样的理论上来思考，但是当初谁不能肯定一定会成功。但是为什么他们能勇敢呢? 是因为他们的眼界更广吗、<a href="https://www.zhihu.com/question/314284424/answer/3148781453">看到别人的成功，所以对自己能成功的信心更足</a>、还是带点基因与原生家庭影响。</p><p>我看到一个<a href="https://www.bilibili.com/video/BV17f421R7WZ">关于房价的视频</a>，中说房价是与负债率有关的，负债率低房价更容易涨起来，而到了20、21年中国的负债率已经居高不下了，所以房价很难涨了。正巧，前几天在公司翻到一本21年出版的书籍，里面同样通过一系列的逻辑推理，得出中国房价还会涨的结论。</p><p>所以很多理论调研就像是一个轮子，正说反说都说的通，所以最后的决策就是得看勇气。现在对看各种理论分析，什么<a href="https://mp.weixin.qq.com/s/WyPLD25BziZcabXFkHk8_A">抖音搞电商成功了是因为什么什么</a>，<a href="https://mp.weixin.qq.com/s/mkZH6Ml4FbAdu8v8ZZ6NOA">快手化商业化做的不如抖音好又是什么用户量不够，导致的广告单价上不去</a>。</p><p><img alt="房价的逻辑" src="https://img.778917.xyz/brave/book_cover.jpg"/> <img alt="结论是中国房价还会上升" src="https://img.778917.xyz/brave/summary.jpg"/></p><h2 id="">我的越来越小的勇气</h2><p>我感觉我的胆子越来越小了，这几天进了几次医院，先是健身导致了横纹肌溶解、然后回家骑车的时候摔了，再接着是打羽毛球的时候，头盖骨被狠狠的扣了一球拍。人们常说人教人教不会，事教人一教就会，我以后上重量肯定不会那么极限了，雨天骑车的时候速度会更慢、运动的时候也会更加小心。</p><p>在这些事上小心看起来确实没有问题什么，也对我不会有什么明显的害处，但是如果我对我的职业选择更加保守呢? 如果我要选择工作，我是选择一家创业公司还是一家大公司? 如果让我选择城市，我是选择去北上广深去漂还是回老家有房挣的少一点呢?</p><p>我现在遇到的各种挫折可能就会让我变得保守，可能就让我放弃更好的机会。</p><h2 id="">踩在风口上的人</h2><p>你们说那些在房价上涨之前做出决策的人，那些买房的人，他们敢做这么大的决策是因为他们有多聪明吗? 做出多少研究吗? 可能只是因为勇敢吧，那为什么会这样勇敢呢，可能是他们上一次做出勇敢的决定成功，所以他们这次又勇敢了。那些决策相对保守人，他们在做买房决策的可能就有更多的犹豫，错过了风口。</p><p>王兴在做出美团之前，考上清华大学，再做出校内网、饭否网。确实是一路成功，那么他在美团遇到各种风险的时候确实会有更多的勇气。如果他的前几个项目失败了，说不定他会变的更加保守，美团可能也没有今天这么成功了。</p><p>那些由于勇敢而成功的人，可能对比另一批失败者，他们只是之前的运气更好而已。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/life/brave#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/life/brave</link><guid isPermaLink="true">https://blog.778917.xyz/posts/life/brave</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Sun, 30 Jun 2024 00:00:00 GMT</pubDate></item><item><title><![CDATA[Launch『ToFree』一周后，我做一个小总结]]></title><description><![CDATA[<link rel="preload" as="image" href="https://img.778917.xyz/why-to-free/tofree.png"/><link rel="preload" as="image" href="https://img.778917.xyz/why-to-free/star.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/tech/why-to-free">https://blog.778917.xyz/posts/tech/why-to-free</a></blockquote><div><h2 id="tofree-">ToFree 是什么?</h2><p><a href="https://tofree.zeabur.app">ToFree</a> 是一个自动抓取 WARP+ 节点信息并将其转换成 Clash、Surge、WireGuard 等软件可订阅使用的工具。</p><p><img alt="ToFree网站的截图" src="https://img.778917.xyz/why-to-free/tofree.png"/></p><h2 id="-tofree">为什么我要搞 ToFree?</h2><p>WARP+ 应该是 2023 年推出的一款代理服务，因为能在中国大陆使用、并且免费的原因。很快就有大量的教程出来教大家如果在 Surge、Clash 上使用 WARP+ 的节点。我也在那时候尝试了一下。那时候我认识虽然免费而且速度勉强可以，但是这不值得我省下一个月几十块的机场钱。所以我再也没有用过了。但是这其实上是我忽略掉了 WARP+ 的一个很重要的价值。</p><p>我很早之前就看到<a href="https://program-think.blogspot.com/2020/08/Tor-Triple-Proxy.html">编程随想教使用 Tor 匿名的文章</a>，其中提到使用赛风、自由门等等软件做为 Tor 前置代理。在我短暂的使用 Tor 的经历中我从来没有用过这些软件，因为这些软件虽然免费，但是无不是又卡又慢。对于我来说根本无法使用。所以我一直使用付费的机场作为 Tor 的前置代理。</p><p>但是在前段时间，我意识到如果在 Tor 前使用这些机场的代理，那么匿名的效果就会很差多。因为你在机场留下了付费的信息。所以我一直忽略了免费的另一面: 匿名。</p><p>所以我就想尝试通过订阅的方式为不同的代理软件提供免费、匿名的 WARP+ 代理。其竞争对手并不是付费的机场，而是之前那些免费的 Tor 前置代理软件。</p><h2 id="">经历</h2><p>我有了这个想法一起就爬了起来，先在 GitHub 上搜索有没有人已经有了实现。幸运的是我一下就搜索到了。我尝试了一下，其功能还是可以工作的，实在太棒了，说明这个 ToFree 项目不会消耗我的太多精力与时间。</p><p>然后我做了一些优化，加了一个好看的前端界面，写一些代码解决了一些小 Bug，然后支持了 Surge 的订阅。部署在 Zeabur 上。然后在 V2EX 上做 Launch。没想到收获到了意料之外的关注度。</p><p>随便在尝试在阮一峰的周刊与 HelloGitHub 上再 Launch 一次，可惜没有过审。</p><h2 id="">整体设计</h2><p>我对 WARP CLASH API 的主要改造是对用户体验上的改造。首先是网站的上手难度，其次是订阅链接的简洁性。</p><p>原 WARP Clash API，只提供了订阅链接，而且是非常复杂，在 path 后面还有大量的 param。我先是加了一个无参数，尽可能简单的订阅链接。如<code>https://subs.zeabur.app/clash</code>，这样用户在一台新设备上就可以直接默写出来订阅链接，这个体验其实是非常棒的。特别是在比如别人的设备上，比如帮我对象翻个墙。</p><p>然后加了一些 url schema 自动导入订阅软件这些就没有什么额外说的。🤔</p><p>至于这些改动，已经通过数个 PR 渐渐反馈到上游的开源项目中去。这个我觉得是很重要的，如果你代码用了什么开源项目，做了优化与改动还是得尽可能的反馈给上游与社区。这个并不是出于什么道德。而是可以降低你的维护成本。后续上游有什么修复或者新功能，你同步回来也方便。很有趣，出发点是自私的，但是结果确是对大家都好的。😋</p><h2 id="">收获</h2><p>我从中收获了一个新朋友和大约 5 个新的 Twitter 粉丝。我和该开源项目的开发者成了朋友确实很开心，但是 5 个新的 Twitter 粉丝。确实没有达到我的预期。我在设计之初，希望收获一些关注，比如Twitter 粉丝，然后通过拿马斯克的广告费来盈利。所以我做了一些改造，比如 ToFree 上顶部放上直达 Follow 按扭的 Twitter Link。但是转化效果依然不理想。后续可以研究一下，是什么原因，比如是没有点开，还是用户没有登陆无法关注，或者觉得关注并没有带来价值。🤔</p><p>(Update: 后续长尾运营带来的粉丝还是不少的，大概有 20 ~ 30 个)
(Update: 后续长尾运营又带来了大约 300 个粉丝，这回舒服了)</p>
<p>帮助上游项目 <a href="https://github.com/vvbbnn00/WARP-Clash-API">WARP Clash API</a> 的 Star 大概翻了四倍。
(Update: 后续翻了59倍)</p><p><img alt="帮助 WARP Clash API 在短时间内 Star 翻四倍" src="https://img.778917.xyz/why-to-free/star.png"/></p><h2 id="">反思与总结</h2><p>最后大概来个总结，首先我在 UI/UX 上做的改造不错，解决 WARP 用起来麻烦的痒点，其次是在 Launch 上做的不错。做的还不够好的地方，主要就是后面两次在其它网站的 Launch 没有通过，可能是题材比较敏感或者写的内容不够吸引人。</p><p>这个模式也大概也有个雏形，我可能后面也会尝试继续挖掘生活中感受到的痛点，然后寻找是否有开源项目，解决开源项目常出现的 UX 不够友好的问题。然后发布，帮助到大家，收获关注。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/tech/why-to-free#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/tech/why-to-free</link><guid isPermaLink="true">https://blog.778917.xyz/posts/tech/why-to-free</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Tue, 06 Feb 2024 08:27:09 GMT</pubDate></item><item><title><![CDATA[为了降低成本，我把 MongoDB 从 TechStack 移除了]]></title><description><![CDATA[<link rel="preload" as="image" href="https://img.778917.xyz/reduce-cost-of-techstack/techstack-usage.png"/><link rel="preload" as="image" href="https://img.778917.xyz/reduce-cost-of-techstack/uninstall-mongodb-compass.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/tech/reduce-cost-of-techstack">https://blog.778917.xyz/posts/tech/reduce-cost-of-techstack</a></blockquote><div><h2 id="techstack-">TechStack 是什么?</h2><p><a href="https://github.com/Get-Tech-Stack/TechStack">TechStack</a>是我去年开发的一款浏览器插件。大约收获了 400+ 的 Star 与 900 的日活。这个插件可以在 GitHub 仓库旁边显示当前仓库的技术栈。这个插件的初衷是为了帮助开发者更好的了解一个项目的技术栈，以便更好的学习和使用。</p><p>但是我最近减少对插件的开发与维护，并且在最近进行了一些小重构以降低成本。在这里我想谈谈为什么这不是一款好的软件和我为什么减少维护。</p><h2 id="techstack-">TechStack 为什么不是一个好软件?</h2><p>TechStack 算是我第一款『完成的 Side Project』。收获了一点点小关注。但是现在事后回过头来看，这个并不是一个『好软件』，我从来没有进行过市场分析、调研。也没有研究过开发者的需求。只是觉得这样一定很酷很有用，所以就开始做了。</p><p>但是事实上，虽然我每天都在使用(被动地)，但是我感觉我没有被帮助到，解决掉我的什么痛点或者痒点。对于这个插件，我最初的设想也很宏伟，不仅仅只是一个插件，还是一个入口、起点。我可以通过收集到的数据进行各种分析与分享。</p><p>比如我还可以再做一个网站来分析技术栈的使用情况，比如被应用到实际开发中的增长趋势。对比不同的技术栈应用情况来帮助用户在选择技术上时更好的决策。</p><p>以及用户可以选一些技术栈，找到一个项目，看看别人的代码是怎么写的。比如选择 Flink 和 Pulsar、 gRPC 和 SWR 这样通过拼接技术栈来找到一个项目。学习应该怎么写。</p><p>但是最后都没有实现，主要不是技术原因，还是我觉得这些并没有解决掉什么痒点和痛点，大家其实并不需要这个。</p><h2 id="techstack-">TechStack 需要降低成本?</h2><p>因为 TechStack 已经停止功能开发了，而且也绝不会从中获得任何收益。所以我觉得我需要必须降低运行成本，这里主要指服务端的成本。本来这个 TechStack 的运营成本确实很低，但是随着数据量的增长，已经高到一个让我难以接受的地步。</p><p><img alt="TechStack 在 Zeabur 上用量 Usage 的截图" src="https://img.778917.xyz/reduce-cost-of-techstack/techstack-usage.png"/></p><p>这些图是我一个 Zeabur 的账号的费用用量图，可以看到最大的成本支出是 TechStack 的数据库 MongoDB 所占用的。光数据库一个月的支出就将近 200+ 人民币。这个成本对于我来说是不可接受的。</p><p>这里谈谈 TechStack 在 MongoDB 中存了什么和为什么这么大的用量。TechStack 的最初的设计上使用两级缓存的机制，一级缓存是存储一个仓库对接的技术栈，有 1 天的过期时间。然后二级缓存是仓库对应的依赖文件，其就存储在 MongoDB 中。这样做的原因是因为早期我对 TechStack 的依赖项对应技术栈更新很频繁。所以我觉得这样做可以减少对 GitHub 的依赖文件的请求次数，缓存过期之后就可以用新的解析器对缓存好的依赖文件进行重新解析。</p><h2 id="techstack-">TechStack 是如何降低成本的?</h2><p>首先已经找出最大的问题所在，就是 MongoDB 的存储成本。我现在不需要存储这些依赖文件的内容了，所以我就用<a href="https://github.com/dtm-labs/rockscache"><code>rockscache</code></a>做了二级缓存，现在只缓存解析出来的结果，</p><p>所以现在可以把 MongoDB Compass 也给一起删掉啰! 我一点也不喜欢这个 electron 应用。又卡又慢一点也不好用，除了好看。</p><p><img alt="用 Brew 卸载 MongoDB Compose 的截图" src="https://img.778917.xyz/reduce-cost-of-techstack/uninstall-mongodb-compass.png"/></p><p>当然 TechStack 是一个非常大的异构项目，像 Request TechStack 的后端、Gradle Parser 等等是用 Java 来实现的，内存占用也是十分的大。尽管这次我还没有移除它们，但是在未来我也会考虑降本增效(笑)🤣。</p><h2 id="-techstack-">我从 TechStack 学到了什么?</h2><p>前面提到 TechStack 算是我第一款『完成的 Side Project』。所以我在这里开发中，还是学到特别特别多的东西。包括工程化的开发、监控还有很多很多工具，像是 Prometheus、Grafana、Flink、 Nest.js、Prism 等等。而且很多时间是为了学新技术而去用新技术。所以在很多地方采用了不是最优实践，也图增成本。</p><p>抛开技术不谈，就是学到运营与宣发，确实找到了很多平台。知道哪些平台能有流量，哪些没有。和应该怎么发。还有在这期间尝试去学习产品经理的理论与方法论。</p><p>在下一篇文章我可能谈谈<a href="https://tofree.zeabur.app/">ToFree</a>，这也是一个免费、开源的项目。这个项目虽然是冷启动，但是收获了不少的关注，也帮助一个开源项目的 Star 翻了数倍。我想谈谈我是怎么想到，付了一个很低的成本，然后收获了一些不小的关注与用户，但是为什么我没有从中得到我想要的。做一些反思与总结。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/tech/reduce-cost-of-techstack#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/tech/reduce-cost-of-techstack</link><guid isPermaLink="true">https://blog.778917.xyz/posts/tech/reduce-cost-of-techstack</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Fri, 02 Feb 2024 12:11:21 GMT</pubDate></item><item><title><![CDATA[2023年终总结]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/life/2023-summary">https://blog.778917.xyz/posts/life/2023-summary</a></blockquote><div><h2 id="">今年总结</h2><p>全年围绕着开坑与弃坑，但是确实感觉今年是进步最大的一年。不仅在技术上的进步比较大，在不断的开坑中，更深刻的了解了不同架构与最佳实践。还把前后端中的除了 CRUD 以外的细节了解的更明白了(可能说起来微不足道，无非就是缓存、骨架图等等)。</p><p>除了技术上进步，在一次又一次开坑中我对产品感觉也更进一了步。读了不少产品向的书，对用户故事、信息架构等等都有一些了解。能通过定位去思考产品的价值等等。尽管开的坑感觉还是不断的弃坑，但是我还是觉得还可以，快速失败嘛，不怕失败，只希望能在不断的失败中进步。</p><h2 id="1">1月</h2><p>结束了大三上，开始放寒假，从福大交换回来了。挂了一科数值计算。</p><p>在家里给自己组了一套 <a href="https://correctroadh.github.io/posts/diy-nas">NAS</a>，没有想命运的齿轮开始转动。🙈为我的第一份工作埋下了伏笔。</p><h2 id="2">2月</h2><p>想到一个 idea，叫『学了啥』，对世面上所有的网课、视频课(比如少数派、极客时间的课)做一个评分网站(类似豆瓣)。但是没有开坑。</p><p>因为一直在用 Linux，所以想用 Flutter 整一个全平台的 Omnifocus。学了一阵 Flutter 没有后续。</p><h2 id="3">3月</h2><p>因为想锻练一下代码水平开始参加开源项目: <a href="https://github.com/usememos/memos">Memos</a>。没想到又给人生埋下了伏笔。🙈</p><p>在 Memos 中开发者给我推荐了 Zeabur，成为Zeabur前一百个付费用户。本来想给家里的 nas 做反代，后面发现没办法这样做。</p><h2 id="4">4月</h2><p>给 Bytebase 投了简历，可惜没有后续。</p><p>参加 Bytebase 的另一个开源项目 <a href="https://github.com/sqlchat/sqlchat">SQL Chat</a>，可惜这个项目没有火，Bytebase 估计也看到这个项目确实不太行，也没有继续投入什么精力了。</p><p>现在看起来基于 Chat 的交互方式确实是一个很不错的 idea，而且 SQL 软件确实用起来比较复杂，如果能用 Chat 的方式去交互确实能降低学习成本。但是似乎又确实没有真的解决掉用户的什么痛点。这个可能确实是一个失败的原因。</p><h2 id="5">5月</h2><p>因为解决 Memos 的 Issue，认识了现在的公司 IceWhale，提交了开源之夏申请，可惜没有被选上，感觉有内幕，因为被选上的那个计划书看起来不如我的。</p><h2 id="6">6月</h2><p>拿了 IceWhale 的 Offer，开始学始 Golang。</p><p>又开了一个坑， <a href="https://github.com/Media-Fetch-Pro/Media-Fetch-Pro">Media Fetch Pro</a> ，一个视频下载器工具，可以把 B站，Youtube 视频下载到 Jellyfin、Emby 和 Plex 上。但是在基本功能完善之后发现没有什么人用，就没有继续开发了。</p><p>把学了啥这个项目在期末做成课程作业水了一下交了。</p><h2 id="7">7月</h2><p>放暑假了，一个人孤身来深圳在 IceWhale 开始实习。</p><h2 id="8">8月</h2><p>又开了一个新坑，开始整 <a href="https://github.com/Get-Tech-Stack/TechStack">TechStack</a>，一个浏览器插件，可以显示 GitHub 仓库的技术栈。</p><h2 id="9">9月</h2><p>学习了 Flink
继续整 TechStack，开始高强度的写软文与推广，效果一般。</p><h2 id="10">10月</h2><p>继续整 TechStack，重构代码与实现后台。但是感觉这个项目其实没有什么意义，感觉可能并没有真的解决掉用户的痛点。所以渐渐减少了对这个项目的投入。</p><h2 id="11">11月</h2><p>开坑，一个关于阅读工具，结合了阅读与社交。就是在阅读 PDF 时可以高亮内容。然后对高亮的内容进行评论。感觉能提高学习效率。还挺有用的。</p><p>学习 K8s ，但是没有学明白🥲。</p><h2 id="12">12月</h2><p>开坑 <a href="https://github.com/CorrectRoadH/Likit">Likit</a>，一个点赞系统的 Backend as a service，主要是给前端读书工具用的，但是感觉价值不是很大。所以也没有继续开发。</p><p>继续完成读书的软件，拉了一些学弟组成计算机经典读书会，一起阅读。但是感觉大家都是读几天都读不下去了。怀疑这个阅读工具的价值。</p><p>这个月还学习了很多信息架构、产品的书籍与知识。尝试用业界流行的工具与方法对我想开坑的去分析与讨论。现在开坑也要到处问问别人的意见了。不会先写代码。比如<a href="https://v2ex.com/t/1004526">这个 idea，就是想到一个关于文件管理的</a>。</p>
<p>不过看起来反馈不够理想，可能也没有后续了。 然后可能会尝试做一个本地代码管理工具，从前面的文件管理抽出来的。比如解决一下，要拉 GitHub 上的代码得找个地方放的痒点与 fork 一个拉下来的项目还得回 GitHub Fork 和改本地的 remote 之类的痒点。但是感觉这个 idea 也不是很好，主要就是没有解决到用户的痛点。所以看看反馈再决定要不要开坑。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/life/2023-summary#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/life/2023-summary</link><guid isPermaLink="true">https://blog.778917.xyz/posts/life/2023-summary</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Sat, 30 Dec 2023 00:00:00 GMT</pubDate></item><item><title><![CDATA[我在开发浏览器插件 TechStack 时遇到的一些坑]]></title><description><![CDATA[<link rel="preload" as="image" href="https://img.778917.xyz/google-extension-problem/1.png"/><link rel="preload" as="image" href="https://img.778917.xyz/google-extension-problem/2.png"/><link rel="preload" as="image" href="https://img.778917.xyz/google-extension-problem/image.png"/><link rel="preload" as="image" href="https://img.778917.xyz/google-extension-problem/5.png"/><link rel="preload" as="image" href="https://img.778917.xyz/google-extension-problem/3.png"/><link rel="preload" as="image" href="https://img.778917.xyz/google-extension-problem/4.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/tech/google-extension-problem">https://blog.778917.xyz/posts/tech/google-extension-problem</a></blockquote><div><p>PS: 本文写于  2023-08-25 ，但是因为最近基本所有的下班时间都趴在 <a href="https://github.com/Get-Tech-Stack/TechStack?ref=blog">TechStack</a> 上，再加上本人的拖延症一直犯，所以在咕了两个月之后才写好。🤣</p><h3 id="">谷歌插件无法过审</h3><p>我的浏览器插件已经两周没有更新了，倒不是我没有写代码，而是总是被不停的拒绝并且没有任何的理由😭。所以我在不停的尝试代码中的各种地方，但是就是不能过审
<img alt="1.png" src="https://img.778917.xyz/google-extension-problem/1.png"/></p><p>最早以为是我的代码中有一个feedback(用了mailto)，点击就触发邮箱应用。是因为这个原因不能过审。
<img alt="1.png" src="https://img.778917.xyz/google-extension-problem/2.png"/></p><p>但是在每天晚上被拒绝一次之后我又提交一次之后并且每天晚上骂谷歌十分钟之后的今天我终于发现几封未读的邮件。🤯原来谷歌在这里把拒绝原因分开来发，倒不是我没有想到，主要是行为的不一致性，因为有时候拒绝原因是写在 Developer Dashboard 中的，如下图。 让人容易产生误解。以为就是只在 Developer Dashboard 通知开发者，根本没有想还会通过邮件通知开发者。
<img alt="Alt text" src="https://img.778917.xyz/google-extension-problem/image.png"/></p><h4 id="">解决办法</h4><p>既然知道问题了就要解决问题。大概就是我提交的代码中不能混淆。但是我的插件是基于 GitHub 上的 boilerplate ，别人怎么就能用这个 boilerplate ，我不行?😅</p><p>首先看一眼代码，确实感觉混淆在一起了把这里 minimize 改掉。
<img alt="对比" src="https://img.778917.xyz/google-extension-problem/5.png"/>
现在来看看效果，感觉还不错。大概有了代码的样子，但是这个应该还是babel转义过了🤔但是确实没有被混淆了。估计能过。</p><p>结果还是不行。认真看邮件，原来不是说我代码混淆过了。而是说我代码有『混淆』的代码。🤯 这里是指有一些代码是base64的，然后通过base64解密后再eval执行。这怎么可能，我怎么会写这种代码呢?</p><p>定位到原因的代码。原来是 Fingerprint 搞的鬼，定位一下<a href="https://github.com/fingerprintjs/fingerprintjs/issues/734">issue</a>，问题找到了，Fingerprint 在代码中用了Base64又编码了一些代码。无奈只能退回老版本。</p><p>改了之后终于可以比较正常的通过审核了</p><h3 id="firefox---id">Firefox 的 插件 ID</h3><p>Firefox 的拓展是需要一个插件ID的，但是如果你没有给他，其实也是能用的，它会自动分配一个临时ID。但是一定要记的，自己手动分配一个ID。不然就会像我一样惨😭
<img alt="一定要手动给一个插件 ID" src="https://img.778917.xyz/google-extension-problem/3.png"/></p><p>我这里遇到的问题是如果调用 Storage 相关的 API 就一定不能用自动分配的临时ID，而我在做 Options 页的时候会用到 Storage，但是无奈新旧版本的 ID 不一样，不能更新，只能无奈放弃旧的插件用户，不过幸好 Firefox 的用户还少。不至于让一批用户无法更新。</p><p><img alt="无奈只能新开一个插件" src="https://img.778917.xyz/google-extension-problem/4.png"/></p><h3 id="api">不同浏览器的API兼容问题</h3><p>这个主要就是做 Storage，Chrome 和 Firefox 关于插件存储的 API 不一致导致的。 这个通过web polyfill很简单就能解决了。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/tech/google-extension-problem#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/tech/google-extension-problem</link><guid isPermaLink="true">https://blog.778917.xyz/posts/tech/google-extension-problem</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Sun, 22 Oct 2023 00:00:00 GMT</pubDate></item><item><title><![CDATA[一个由 Http Get 引发的 Goroutine 泄漏问题]]></title><description><![CDATA[<link rel="preload" as="image" href="https://img.778917.xyz/go-leak/1.png"/><link rel="preload" as="image" href="https://img.778917.xyz/go-leak/2.png"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.778917.xyz/posts/tech/go-leak">https://blog.778917.xyz/posts/tech/go-leak</a></blockquote><div><h2 id="">问题背景</h2><p>不得不说 Golang 的 DX 做的很舒服，比如在测试有问题的并发代码中会提醒你 Data Race 。这样就不用等你发现数据出问题了，再去找代码的问题。👀 最近开始用的一个很有帮助的工具就是 Goleak。来帮助我们找到泄漏的 goroutine。可以理解成其它语言的线程👀，泄漏意思就是工作做完之后，还有些这个工作开的 goroutine 没有结束。就像申请的内存在使用完之后没有释放一样。</p><p>按<a href="https://zhuanlan.zhihu.com/p/361737398">教程</a>给我的代码测试加个了 goleak 测试。</p><p>但是一下测试， goleak 和我说我的代码有 goroutine 泄漏。🤯 我代码有不少并发代码，但是都是用的 sync.WaitGroup 来控制的。没有<a href="https://www.cnblogs.com/paulwhw/p/17003763.html">网上常见的什么 channel 导致的问题</a>，所以我很奇怪为什么会有 goroutine 泄漏的问题。</p><p>通过给子函数加单元测试二分查找一下，我很快定位问题的位置，并不是我写的并发代码产生的 goroutine 泄漏。这个泄漏居然产生一个 Http 请求的代码里面。🤯</p><p>代码通过简化大概如下 👇</p><p>代码:</p><pre class="language-go lang-go"><code class="language-go lang-go">package httptest

import (
    &quot;net/http&quot;
)

func HttpGet(url string) error {
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    return nil
}
</code></pre>
<p>测试:</p><pre class="language-go lang-go"><code class="language-go lang-go">package httptest_test

import (
    &quot;fmt&quot;
    &quot;runtime&quot;
    &quot;testing&quot;

    &quot;github.com/stretchr/testify/assert&quot;
    &quot;go.uber.org/goleak&quot;

    httptest &quot;test&quot;
)

func TestFail(t *testing.T) {
    fmt.Println(&quot;开始时goroutine的数量:&quot;, runtime.NumGoroutine())

    defer goleak.VerifyNone(t)

    err := httptest.HttpGet(&quot;https://raw.githubusercontent.com/Get-Tech-Stack/TechStack/main/package.json&quot;)
    assert.NoError(t, err)
    fmt.Println(&quot;结束时goroutine的数量:&quot;, runtime.NumGoroutine())
}
</code></pre><p>测试结果: 可以看到结果时的 goroutine 数量比开始时多了一个。说明有一个 goroutine 泄漏了。
<img alt="VSCode 报 Goleak 错误的截图" src="https://img.778917.xyz/go-leak/1.png"/></p><pre class=""><code class="">开始时goroutine的数量: 2
结束时goroutine的数量: 3
--- FAIL: TestFail (0.52s)
    /Users/ctrdh/zeabur_reproduce/main_test.go:22: found unexpected goroutines:
        [Goroutine 36 in state IO wait, with internal/poll.runtime_pollWait on top of the stack:
        goroutine 36 [IO wait]:
        internal/poll.runtime_pollWait(0x109273fc0, 0x72)
            /opt/homebrew/Cellar/go/1.21.0/libexec/src/runtime/netpoll.go:343 +0xa0
        internal/poll.(*pollDesc).wait(0x140000de480?, 0x140001c2000?, 0x0)
            /opt/homebrew/Cellar/go/1.21.0/libexec/src/internal/poll/fd_poll_runtime.go:84 +0x28
        internal/poll.(*pollDesc).waitRead(...)
            /opt/homebrew/Cellar/go/1.21.0/libexec/src/internal/poll/fd_poll_runtime.go:89
        internal/poll.(*FD).Read(0x140000de480, {0x140001c2000, 0x1300, 0x1300})
            /opt/homebrew/Cellar/go/1.21.0/libexec/src/internal/poll/fd_unix.go:164 +0x200
        net.(*netFD).Read(0x140000de480, {0x140001c2000?, 0x1400018e340?, 0x102242674?})
            /opt/homebrew/Cellar/go/1.21.0/libexec/src/net/fd_posix.go:55 +0x28
</code></pre>
<p>如果看到<a href="https://manishrjain.com/must-close-golang-http-response#:~:text=The%20http%20Client%20and%20Transport,may%20not%20reuse%20HTTP%2F1.">我该 close 的都 close 的🤔</a>，在好几个群里问来问去，我尝试换 URL 之类的还出过几个乌龙。最后谷歌了一下，在 <a href="https://stackoverflow.com/questions/75026700/goroutine-leaks-when-trying-to-readallresponse-body-where-response-is-retu/75816347#75816347">stack overflow</a> 找到了问题所在，这个原因是由于<code>http.Get(url)</code>导致的。第二天另一个 Zeabur 的同学也找到了同样的帖子帮我解决了这个问题。🤣这里不得不感谢 Zeabur 了，经常遇到啥技术问题都发在他们工单群里，他们没有踢掉我不说还经常帮我解决问题。</p><h2 id="">解决方案</h2><p>直接上解决该问题之后的代码:</p><pre class="language-go lang-go"><code class="language-go lang-go">func HttpGet(url string) ([]byte, error) {
    req, err := http.NewRequest(&quot;GET&quot;, url, nil)
    if err != nil {
        return []byte{}, err
    }
    client := http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return []byte{}, err
    }
    defer resp.Body.Close()
    defer client.CloseIdleConnections() // &lt;-- 把空闲的连接关闭掉

    result, err := io.ReadAll(resp.Body)
    if err != nil {
        return []byte{}, err
    }

    return result, nil}
</code></pre>
<p>这样就能通过测试了。🎉
<img alt="VSCode 通过 Goleak 测试截图" src="https://img.778917.xyz/go-leak/2.png"/></p><h2 id="">原因</h2><p>上面的 Stack overflow 其实也说了这个问题是因为<code>http.Client</code>使用了<code>Transport</code>，而这个会维护一个连接池保持那些<code>kept-alive</code>的连接。所以我们需要在<code>defer</code>里面调用<code>CloseIdleConnections</code>来关闭这些连接。</p></div><p style="text-align:right"><a href="https://blog.778917.xyz/posts/tech/go-leak#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.778917.xyz/posts/tech/go-leak</link><guid isPermaLink="true">https://blog.778917.xyz/posts/tech/go-leak</guid><dc:creator><![CDATA[ctrdh]]></dc:creator><pubDate>Fri, 25 Aug 2023 00:00:00 GMT</pubDate></item></channel></rss>