Rewrite AI agent article and remove test posts

This commit is contained in:
2026-06-17 22:17:27 +08:00
parent 6bf89079d3
commit 7afe446054
18 changed files with 28 additions and 934 deletions
-50
View File
@@ -1,50 +0,0 @@
---
title: "从 5G 到算力网络:通信行业的技术演进观察"
date: 2026-05-12T23:00:00+08:00
draft: false
poet: |
沉舟侧畔千帆过,
病树前头万木春。
——刘禹锡,中国,772–842
description: "5G 商用五年,哪些超出预期,哪些没达预期。以及下一个五年通信行业的关键方向:云网融合、通感算一体化、AI 原生网络和低空经济。运营商面临的结构性挑战和机会。"
tags:
- 通信
- 5G
- 行业观察
---
入行通信这些年,看着技术代际更迭,有些感触想记下来。
## 5G 的这五年
5G 商用五年,回头看当初的 hype 和现实之间的差距很有意思:
**超预期**的部分:
- 网络能力和覆盖远超 4G
- 行业应用从概念走到落地
- 切片、边缘计算等特性开始产生价值
**没达到预期的部分**:
- C 端杀手级应用迟迟未出现
- 资费下降快,增量不增收
- 数字化转型需求 vs 实际付费意愿之间的鸿沟
## 下一个五年:算力网络
行业现在提的更多的是「算力网络」—— 把通信网络和计算资源统一调度。
几个值得关注的方向:
1. **云网融合** — 网络即服务,算力即服务
2. **通感算一体化** — 通信、感知、计算在基站层面融合
3. **AI 原生网络** — 用 AI 管网络,从辅助运维到自动运维
4. **低空经济** — 无人机、飞行汽车对网络覆盖的新需求
## 运营商面临的挑战
- 传统语音+流量模式见顶
- 云业务面临互联网厂商竞争
- 组织流程迭代跟不上技术迭代速度
- 人才结构转型压力大
不过换个角度看,通信基础设施作为数字经济的「水电煤」,长期价值不会消失,只是价值形态在变。关键是找到自己在价值链中的新位置。
+25 -80
View File
@@ -1,116 +1,61 @@
---
title: "善假说"
title: "养虾试玩报告"
date: 2026-05-16T01:30:00+08:00
draft: false
poet: |
君子生非异也,
善假于物也。
——《荀子·劝学》
description: "近以AI智能体为幕僚,五日亲历,颇有所得。录之以证荀子之言。"
description: "搭了个 AI 智能体,试了五天,记录一下它能干什么。"
tags:
- AI
- 效率
- 杂文
---
{{< figure src="/images/fusheng.jpg" caption="杜堇《伏生授经图》,明,大都会艺术博物馆藏" alt="杜堇《伏生授经图》" >}}
荀子说,君子生非异也,善假于物也。我以前读完也就过了,没细想。
荀子有句话:"君子生非异也,善假于物也。"说白了就是,人和人差别没那么大,关键看你会不会用工具。以前我觉得这话挺对,但也没多想。
AI 这两年用得不少,ChatGPT、Claude、DeepSeek 都试过。问问题、写代码、润文字,确实方便。但模式始终是单向的——它等你问,你问它答,问完结束。
AI 这两年没少用,ChatGPT、Claude、DeepSeek 都试过。问问题、写代码、润文字,确实方便。但模式一直是你问它答,问完就完了。
直到我用上一个能自己干活的智能体。它叫"爪子",跑在腾讯云一台轻量服务器上,4 核 4G,配置不高。搭起来很简单:在服务器上装了一个叫 OpenClaw 的智能体框架,绑好微信,配上 Todoist 和 Git 的 API 密钥,就能远程使唤了。这东西驻扎在服务器上,能直接执行 Shell 命令、读写文件、操作 Git 仓库、浏览网页。从有想法到跑起来,花了半晚上。
直到最近搭了个能自己干活的 AI 智能体,体验不太一样。
## 役物和任人
它叫"爪子",跑在腾讯云一台轻量服务器上,4 核 4G。说起来也是薅羊毛——一百块拿下的,跑着网站、Git 仓库、密码管理一堆服务,性能还绰绰有余。在服务器上装了 OpenClaw,绑好微信、Todoist 和 Git 的 API,就能远程指挥了。这东西驻扎在服务器上,能跑 Shell 命令、读写文件、操作 Git、浏览网页。从有想法到跑起来,花了半个晚上。
同样是 AI,心态不同,用法天差地别。
## 它和 ChatGPT 的区别在哪
**役物**——问一句答一句,答错了你纠,纠完再问。你是指挥,还得盯着每一步。
以前用 AI:你问一句,它答一句。答错了你纠正,纠完继续问。你得盯着。
**任人**——说清楚方向,交给它去做。做完验收就行,中间过程不必过问。
现在用智能体:说清楚要干什么,剩下的它自己弄。做完告诉你一声。
前者把你绑在操作台前,后者让你从执行中抽身。区别不在技术,在心法。
前者把你绑在屏幕前,后者让你可以走开。区别不在技术,在用它的方式。
## 三件事
## 试了五天,举三个例子
试了五天,挑三件说说。
### 搭博客
### 博客
午休时突然想建个站,跟它说了一句。它自己 SSH 上服务器开始干活:装 Hugo、配 Nginx、设 HTTPS、修 404,全自己折腾完。后来换主题换了三次,都是睡前丢一句话,第二天醒来网站已经换好了。
午间忽想建站,交代了一句。它 SSH 上服务器就开始干活。
### 每天早上的资讯推送
```mermaid
flowchart LR
A[我:建个博客] --> B[SSH 登录服务器]
B --> C[安装 Hugo + Nginx]
C --> D[配置 HTTPS]
D --> E{测试通过?}
E -->|否| F[自修权限问题]
F --> D
E -->|是| G[回复就绪]
```
我让它写了个脚本,每天早上 8:30 把国际新闻、科技动态、通信消息编译成简报,推送到微信。
装 Hugo、配 Nginx、设 HTTPS、修 404 错误,全是它自己弄的。后来主题换了三次——PaperMod、terminal、Hextra——都是半夜一句话的事。第二天醒来网站已经跑在新主题上了。
第三天推送没来。没等我问,它自己查了日志发现 DeepSeek API 响应变慢超时了,自动调长时限重发了。
### 资讯推送
### 工作对话转待办
每天早上想看国际新闻、科技动态和通信消息。我让它写了个定时脚本,每天 8:30 推送微信。
同事发的聊天截图丢给它,说一句"入待办"。它读图、认人、提取待办事项、写入 Todoist、标优先级和截止日。原来一分钟的事,现在十秒。
```mermaid
flowchart LR
A[Cron 8:30] --> B[拉取待办 + 新闻]
B --> C[编译简报]
C --> D[推送微信]
D --> E{成功?}
E -->|失败| F[自查超时]
F --> G[延长时限重发]
G --> D
E -->|成功| H[记入日志]
```
## 试着放了更多权限
第三天推送没来。没等我问,它已经查了日志,发现 DeepSeek API 响应变慢导致超时,自动调长时限重发了。
一开始不敢给太多权限,只让它看看日志。后来发现它出错能自己修、操作有日志可查、半夜发消息秒回——慢慢就放心了。
### 工单管理
后来给了它邮箱权限,让它每天扫收件箱:找出只发给我没抄送下属的邮件,拆附件、正文转 markdown、写摘要、关联已有资料,归档到本地工作目录。第二天上班打开文件夹,摘要和附件已经摆好了。
工作对话截图丢过去,说一句"入待办"。
## 最后
```mermaid
flowchart LR
A[我:发聊天截图] --> B[读取并提取信息]
B --> C[创建 Todoist 任务]
C --> D[标优先级 + 截止日]
D --> E[回复确认]
```
有人问这和 ChatGPT 有什么区别。我觉得可以这么理解:ChatGPT 像字典,能查东西但不会替你干活。智能体像秘书,不一定比你懂行,但能替你跑腿。
读图、识人、提取待办、写入 Todoist、标优先级、定截止期。原来要折腾一分钟的事,现在十秒。
投入也不大:薅腾讯云羊毛,一百块拿下 4 核 4G,几套 API 凭证,半晚上就搭好了。
## 信任是试出来的
一开始不放心,只让它看看日志、查查状态。后来发现出错能自愈、操作有日志可查、半夜发消息也能秒回——慢慢就放手了。
**邮件过滤。** 信任更进一步,我给了它 IMAP 权限,让它每天扫收件箱。
```mermaid
flowchart LR
A[每日扫描收件箱] --> B{发给我但<br>没给下属?}
B -->|是| C[建文件夹存档]
C --> D[附件存 / 正文转 md]
D --> E[撰写摘要]
E --> F[关联已有文件信息]
F --> G[入待办跟进]
B -->|否| H[跳过]
```
筛出发给我但没抄送下属的邮件,拆附件、正文转 markdown、写摘要、关联已有资料,分类归档到我本地工作目录的 inbox。第二天上班打开文件夹,摘要和附件已经摆好了。
## 写在最后
有人问:这和 ChatGPT 有什么区别?
我说:**ChatGPT 是字典,这是秘书。** 字典再全,不会替你写材料。秘书不一定比你懂行,但会替你跑腿。
需要什么投入?一台低配云服务器,一套 API 凭证,花半晚上搭环境。门槛不高。
回头看荀子那句话——"善假于物"。最好的工具不是功能最强的,而是能让你从琐事中脱身的。用到某个程度你会发现,真正费脑子的不是"怎么问 AI",而是"什么可以交给 AI"。
这念头一转,效率的瓶颈就从工具变成了自己的想象力。
回头想荀子那句话——"善假于物"。最好的工具不一定是最强的,是能让你少干杂事的。用着用着你会发现,真正要琢磨的不是"怎么问 AI",而是"什么可以交给 AI"。
+1 -1
View File
@@ -1,5 +1,5 @@
---
title: "AI 生产力的唯一落点"
title: "AI 生产力现状"
date: 2026-05-17T18:10:00+08:00
draft: false
poet: |
-54
View File
@@ -1,54 +0,0 @@
---
title: "2026 年 AI 工具链实用观察"
date: 2026-05-12T21:00:00+08:00
draft: false
poet: |
The mind is its own place, and in itself
Can make a Heaven of Hell, a Hell of Heaven.
— John Milton, UK, 1608–1674
description: "2026 年 AI 工具进入务实阶段。实测 DeepSeek V4 Flash 和 Pro 模型的不同场景表现,Agent 智能体的四个落地方向,以及怎么用更少 token 做更多事。"
tags:
- AI
- 工具
- DeepSeek
---
2026 年的 AI 工具生态可以用一个词形容——**务实**。经过前两年的概念爆发,现在已经进入落地阶段。
## DeepSeek 实测
最近深度体验了 DeepSeek V4 系列模型,几点感受:
### V4-Flash
日常使用首选。响应快、性价比高,适合:
- 代码辅助和 debug
- 文档撰写和润色
- 信息检索和整理
- 日常问答
### V4-Pro
复杂场景下表现出色,适合:
- 长文分析和总结
- 多步推理任务
- 代码架构设计
- 领域专业知识问答
账户余额 ¥74.31,按目前用量够跑一阵子。
## 智能体(Agent)趋势
今年 Agent 是主题词。从单纯对话到能独立执行任务的智能体,有几个方向值得关注:
1. **编码 Agent** — 从写代码到提 PR,全流程自动化
2. **文档 Agent** — 自动生成周报、会议纪要、汇报材料
3. **运维 Agent** — 日志分析、异常告警、故障排查
4. **个人助理 Agent** — 日程管理、信息聚合、任务委派
## 怎么用更划算
- 大部分日常任务用 Flash 就行
- 复杂任务才上 Pro,避免资源浪费
- 善用上下文缓存,减少重复 token 消耗
- 配合工具链(MCP、Function Calling)发挥更大价值
AI 工具的价值不在于它能做什么,而在于你用它做了什么。
-52
View File
@@ -1,52 +0,0 @@
---
title: "数据库索引优化实战"
date: 2026-05-10T16:00:00+08:00
draft: false
poet: |
众里寻他千百度,
蓦然回首,那人却在,灯火阑珊处。
——辛弃疾,中国,1140–1207
description: "慢查询分析、联合索引的最左前缀原则、覆盖索引与回表的性能差异。几个真实 SQL 优化案例,从几秒降到毫秒级。"
tags:
- 数据库
- SQL
- 性能
---
`EXPLAIN` 是 DBA 的眼睛。看 `type` 字段从 `ALL` 变成 `ref` 是最有成就感的事。
## 从慢查询开始
一切优化从定位问题开始。打开 MySQL 的慢查询日志(`slow_query_log`),设置 `long_query_time = 0.1`,跑一段时间后分析。PostgreSQL 用 `pg_stat_statements` 扩展,同样有效。
拿到慢查询,先 `EXPLAIN` 看执行计划。关注几个关键字段:
| 字段 | 含义 | 目标 |
|------|------|------|
| type | 访问类型 | 至少到 range,最好到 ref/const |
| key | 使用的索引 | 不为 NULL |
| rows | 扫描行数 | 越小越好 |
| Extra | 额外信息 | 避免 Using filesort / Using temporary |
## 最左前缀原则
联合索引是最容易出错的地方。假设索引是 `(a, b, c)`:
- `WHERE a = 1` ✅ 用到索引
- `WHERE a = 1 AND b = 2` ✅ 用到索引
- `WHERE b = 2` ❌ 用不到
- `WHERE a = 1 AND c = 3` ⚠️ 只用到了 a 列
排序也受这个规则约束。`ORDER BY a, b` 没问题,`ORDER BY b, c` 就需要额外排序。
## 覆盖索引
如果查询需要的所有列都在索引里,就不需要回表取数据。`Extra` 列显示 `Using index` 就是覆盖索引。对一个高频查询,覆盖索引能减少大量随机 I/O。
代价是索引变大了。不要为了覆盖索引把所有列都塞进索引——算一笔写入性能和存储空间的账。
## 真实案例
某个订单列表查询,原始 SQL 跑了 8 秒。`EXPLAIN` 一看,`type: ALL`,全表扫描 200 万行。加了 `(user_id, created_at)` 联合索引后,`type: ref`,扫描 20 行,耗时 12ms。
**索引不是越多越好**——每个索引都会拖慢写入速度并占用磁盘空间。建索引前问自己:这个查询的执行频率值得一个索引吗?
-52
View File
@@ -1,52 +0,0 @@
---
title: "家庭网络与 NAS 搭建方案"
date: 2026-05-17T15:00:00+08:00
draft: false
poet: |
此心安处是吾乡。
——苏轼,中国,1037–1101
description: "软路由、Wi-Fi 6 AP、自建 NAS 的硬件选型和软件方案。Plex 媒体服务器 + Syncthing 文件同步 + Tailscale 远程访问,一套低成本高品质的家庭网络实践。"
tags:
- NAS
- 网络
- 硬件
---
折腾家庭网络的终点是克制。和 Linux 桌面美化一样,容易用力过猛。本文记录一套低成本但够用的家庭网络方案。
## 网络拓扑
```
光猫 → 软路由(OpenWrt)→ 交换机
├── Wi-Fi 6 AP ×2
├── NAS(TrueNAS)
└── 有线设备
```
软路由选 J4125 或 N100 这类低功耗 x86,刷 OpenWrt,负责拨号、DHCP、科学上网。AP 选 Wi-Fi 6 的,TP-Link XDR 系列性价比不错,刷 OpenWrt 或者用原厂固件都可以。
两个 AP 组 Mesh,不需要折腾 AC 控制器。家里 120 平米基本无死角覆盖。
## NAS 硬件与系统
旧电脑加几块硬盘就是一台 NAS。电费要算:不要拿老 i7 加独显当 NAS,待机功耗四五十瓦,一个月电费够买半块硬盘。
推荐方案:J4125 或 N100 小板 + 8GB 内存 + 2~4 块 4TB 硬盘组 RAID-Z1。系统选 TrueNAS Scale,基于 Linux,容器和虚拟机支持比 Core 版更好。待机功耗 15W 左右,一年电费不到一百块。
## 软件方案
三个核心应用:
| 软件 | 用途 | 替代方案 |
|------|------|----------|
| **Plex** | 媒体服务器,自动刮削海报和元数据 | Jellyfin(开源免费) |
| **Syncthing** | 文件同步,多设备自动备份照片和文档 | Resilio Sync |
| **Tailscale** | 虚拟局域网,外面也能访问家里的服务 | ZeroTier、WireGuard 裸配 |
Plex 装在 TrueNAS 的 App 里,显卡直通给 Plex 做硬件转码——手机上用较低码率看片时自动转码,画质损失不大。Syncthing 每台设备装一个,照片目录设为"仅发送",电脑上的文档文件夹设为"双向同步"。
Tailscale 是真正的体验质变。不需要公网 IP,不需要端口转发,不需要记 IP 地址。手机、笔记本、NAS 在同一个虚拟局域网里,出门在外访问 Plex 和 NAS 文件就像在家一样。免费版支持最多 100 台设备,个人用完全够。
## 总结
方案的核心思路:**够用即可**。不要想着一步到位,先从旧硬件开始跑起来,哪里不够补哪里。家庭网络的价值在于稳定无声地跑着,不是折腾本身。
-36
View File
@@ -1,36 +0,0 @@
---
title: "Linux 桌面美化指北"
date: 2026-05-11T10:00:00+08:00
draft: false
poet: |
My house, my house, though you are small,
You are a mansion to me after all.
— Robert Herrick, UK, 1591–1674
description: "从默认 Gnome 到一套顺手的桌面环境。GTK 主题、图标包、终端配色、窗口管理器的选择与配置思路。不追求花哨,追求每天盯着看不累。"
tags:
- Linux
- 桌面
- 效率
---
Linux 桌面环境的选择很多,但真正好用的配置往往很简单。本文记录从 Ubuntu 默认桌面开始,逐步调整到一套耐看、高效的配置。
## 主题选择
白天用亮色主题降低反光,晚上切暗色保护眼睛。推荐 **Nord** 和 **Catppuccin** 两套配色——前者冷峻克制,后者柔和温暖,每天盯着看八小时不累。
GTK 主题建议选择维护活跃的项目,避免 Gnome 大版本升级后样式错乱。Qt 应用在 Gnome 下可以用 `qt5ct` 统一风格。
## 字体配置
终端字体一定要等宽且清晰。推荐 **Fira Code** 做编程字体,连字(ligatures)让 `=>`、`!=`、`>=` 这类符号组合更易读。中文字体用 **Noto Sans CJK**,和西文搭配自然。
## 终端与 Shell
终端模拟器推荐 **Alacritty**——GPU 加速,配置文件清晰。配合 zsh + **starship** 提示符,日常使用效率提升不少。Starship 的优势在于跨 shell 兼容,换到 fish 或 nu 不用重新配置。
## 窗口管理
Gnome 默认的三指滑动切换工作区已经很好用。如果追求更极致的键盘操作,可以试试 **Pop Shell** 平铺扩展,或者直接上 **i3/sway**。但对大多数人来说,Gnome 的默认交互已经够用。
关键原则:**不追求花哨,追求每天盯着看不累。**
-49
View File
@@ -1,49 +0,0 @@
---
title: "2026 上半年阅读清单与推荐"
date: 2026-05-12T16:00:00+08:00
draft: false
poet: |
书卷多情似故人,
晨昏忧乐每相亲。
——于谦,中国,1398–1457
description: "上半年读过值得推荐的几本书。《软件设计的哲学》讲复杂度管理,《深度工作》讲专注力训练,《凤凰项目》用小说讲 DevOps。附我的阅读节奏安排。"
tags:
- 阅读
- 书单
- 推荐
---
上半年读了十几本书,挑几本值得推荐的记一下。
## 技术类
### 《软件设计的哲学》
不是讲设计模式的,而是讲**复杂度管理**。核心观点:软件设计的本质是降低复杂度。写得深入浅出,适合有几年经验想突破瓶颈的开发者。
### 《凤凰项目》
用小说的形式讲 DevOps 转型。IT 运维的日常在书里无比真实,读起来很有代入感。
## 效率类
### 《深度工作》
Cal Newport 的代表作。核心论点:在这个随时被打断的时代,深度专注的能力越来越稀缺,也越来越有价值。
书里给了一些具体的训练方法,比如:
- 安排固定的深度工作时间段
- 社交媒体断舍离
- 用仪式感帮助进入状态
## 人文类
### 《你以为你以为的就是你以为的吗?》
一本有意思的思维训练书,帮助识别日常思考中的逻辑漏洞。适合碎片时间翻几页。
## 阅读习惯
今年调整了阅读方式:
- **早上的时间给深度阅读** — 30 分钟,不碰手机
- **通勤时间给信息类阅读** — RSS、Newsletter、技术文章
- **周末下午给整本书** — 泡杯茶,一次读一两章
读书不求多,读完、消化、能用上,一本顶十本。
-76
View File
@@ -1,76 +0,0 @@
---
title: "REST API Design: Mistakes I've Made So You Don't Have To"
date: 2026-05-13T09:00:00+08:00
draft: false
poet: |
Form follows function.
— Louis Sullivan, US, 1856–1924
description: "Lessons from real-world API design. Why version early, paginate everything, standardize error responses, and add idempotency keys. Plus a practical deprecation strategy with Sunset headers."
tags:
- API
- REST
- Backend
---
I've designed, built, and maintained enough REST APIs to have made most of the classic mistakes. Here's what I wish someone had told me upfront.
## 1. Versioning Early
Don't wait until you need it. Version your API from day one, either in the URL (`/v1/users`) or via the `Accept` header. Retrofitting versioning onto an unversioned API is painful for everyone involved.
My preference: **URL-based versioning**. It's visible, impossible to forget, and trivially cacheable.
## 2. Pagination by Default
Every list endpoint should be paginated. Every. Single. One.
```json
{
"data": [...],
"pagination": {
"cursor": "eyJpZCI6MTIzfQ==",
"has_more": true,
"total": 847
}
}
```
I've moved from offset-based to cursor-based pagination almost everywhere. Cursors handle real-time data changes gracefully and perform better on large datasets.
## 3. Error Responses Should Be Consistent
A predictable error shape means less client-side code:
```json
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Account balance too low for this transaction",
"details": {
"required": 29.99,
"available": 12.50
}
}
}
```
Never expose stack traces in production. Never leak internal IDs without intent.
## 4. Idempotency Keys
For any mutating endpoint, support an `Idempotency-Key` header. Your payment team will thank you, and so will your users when a retry doesn't double-charge them.
## 5. Think in Terms of Deprecation
Add a `Deprecation` and `Sunset` header to old endpoints:
```
Deprecation: true
Sunset: Sat, 01 Aug 2026 00:00:00 GMT
```
Give consumers time to migrate, then actually follow through on removal. Keeping deprecated endpoints around "just in case" is technical debt with interest.
---
Good API design is mostly about **empathy for the consumer**. Ask yourself: would *you* enjoy integrating with this?
-99
View File
@@ -1,99 +0,0 @@
---
title: "Rust Error Handling: From unwrap to anyhow"
date: 2026-05-16T13:00:00+08:00
draft: false
poet: |
If you can meet with Triumph and Disaster
And treat those two impostors just the same;
— Rudyard Kipling, UK, 1865–1936
description: "The journey from panic-driven development to proper error types. When to use thiserror for library crates and anyhow for applications."
tags:
- Rust
- Error Handling
- Programming
---
Rust forces you to think about errors. Starting with `unwrap()` everywhere is fine for prototypes, but production code needs proper error types.
## Stage 1: The Unwrap Phase
```rust
let config = read_config().unwrap();
let db = connect(&config).unwrap();
let result = query(&db).unwrap();
```
Every Rust beginner goes through this. It's fine for scripts and prototypes — if something fails, the panic message with a line number is good enough. The problem starts when you need graceful error handling or meaningful error messages for users.
## Stage 2: Box<dyn Error>
The quick upgrade path:
```rust
fn do_thing() -> Result<(), Box<dyn std::error::Error>> {
let config = read_config()?;
let db = connect(&config)?;
query(&db)?;
Ok(())
}
```
The `?` operator works with any error type that implements `From<T>`. `Box<dyn Error>` catches everything. But you lose type information — the caller can't match on specific error variants.
## Stage 3: Proper Error Types with thiserror
For libraries, define explicit error types:
```rust
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("configuration error: {0}")]
Config(String),
#[error("database error: {0}")]
Database(#[from] sqlx::Error),
#[error("not found: {0}")]
NotFound(String),
}
```
The `#[from]` attribute auto-implements `From<T>`, so `?` works seamlessly. Callers can match on variants:
```rust
match do_thing().await {
Err(AppError::NotFound(id)) => { /* handle 404 */ }
Err(e) => { /* log and return 500 */ }
Ok(data) => { /* success */ }
}
```
## Stage 4: Application Errors with anyhow
For binaries, `anyhow` provides flexible error handling without the ceremony:
```rust
use anyhow::{Context, Result};
fn main() -> Result<()> {
let config = read_config()
.with_context(|| "failed to read config file")?;
let db = connect(&config)
.context("database connection failed")?;
Ok(())
}
```
`context()` and `with_context()` attach human-readable messages at each fallible step. The error output is a chain of contexts, making debugging straightforward.
## The Ecosystem Split
| Crate | Use Case | Key Feature |
|-------|----------|-------------|
| `thiserror` | Library crates | Derive macro, typed errors |
| `anyhow` | Application binaries | Context chains, easy `?` |
| `eyre` | Applications (alternative) | Colorful error reports, custom hooks |
The ecosystem has settled on this pragmatic split: **thiserror for libraries, anyhow for binaries**. Libraries expose typed errors so callers can react programmatically; applications benefit from rich, human-readable error chains.
Remember: `unwrap()` and `expect()` still have their place — in tests, in examples, and when an invariant violation truly merits a panic. But for production code paths, make errors part of your type signature.
-49
View File
@@ -1,49 +0,0 @@
---
title: "Svelte 初体验:不一样的思路"
date: 2026-05-10T09:30:00+08:00
draft: false
poet: |
Do not go gentle into that good night.
Rage, rage against the dying of the light.
— Dylan Thomas, UK, 1914–1953
description: "试用了 Svelte 5 的 runes 语法和 SvelteKit 框架。没有虚拟 DOM,编译时直接把组件转成 DOM 操作代码,打包体积小得惊人。"
tags:
- Svelte
- 前端
- JavaScript
---
用惯了 React 和 Vue,第一次接触 Svelte 的时候确实有种新鲜感。最直观的感受:**代码量少了很多**。
## Runes 语法
Svelte 5 引入了 runes 语法,让响应式声明更显式:
- **`$state`** — 声明响应式变量,替代了之前靠赋值触发响应式的隐式规则。
- **`$derived`** — 衍生值,类似 Vue 的 computed。
- **`$effect`** — 副作用,自动追踪依赖并在变化时执行。
```svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
$effect(() => {
console.log(`count is now ${count}`);
});
</script>
```
逻辑清晰,没有 `useEffect` 的依赖数组心智负担。
## 编译时魔法
Svelte 的核心理念:没有虚拟 DOM,编译器在构建时直接把组件转成高效的 DOM 操作代码。打包体积小得惊人,一个简单的组件可能只有几百字节。对移动端场景尤其友好。
## SvelteKit
SvelteKit 是 Svelte 的全栈框架,文件路由设计简洁。约定优于配置——新建一个 `src/routes/about/+page.svelte`,就自动有了 `/about` 路由。内置 SSR、SSG、CSR 多种渲染模式,服务器端数据加载用 `load` 函数,类型安全做得不错。
## 总结
Svelte 适合想要减少样板代码、追求小打包体积的项目。React 和 Vue 的生态更成熟,但 Svelte 的思路值得关注。下一步打算用 SvelteKit 重写个人博客试试看。
-67
View File
@@ -1,67 +0,0 @@
---
title: "Migrating to Tailwind CSS v4"
date: 2026-05-13T08:00:00+08:00
draft: false
poet: |
苟日新,日日新,又日新。
——《礼记·大学》,中国
description: "CSS-first configuration, the new @theme directive, container queries, and what actually changed from v3. A practical migration log."
tags:
- CSS
- Tailwind
- Frontend
---
Tailwind v4 drops the JavaScript config file in favor of CSS-based configuration. The migration is mostly mechanical but there are gotchas with the `@apply` directive and custom variants.
## CSS-First Configuration
The biggest change: `tailwind.config.js` is replaced by CSS. Your design tokens live in the `@theme` directive:
```css
@import "tailwindcss";
@theme {
--color-primary: #2563eb;
--color-primary-dark: #1d4ed8;
--font-sans: "Inter", sans-serif;
--spacing-container: 1280px;
}
```
VSCode IntelliSense still works — the Tailwind CSS extension reads theme values from your stylesheet.
## The Migration Path
1. Install v4: `npm install tailwindcss@next`
2. Run the automatic migration tool: `npx @tailwindcss/upgrade`
3. Manually check `@apply` usages — the tool handles most cases, but deeply nested `@apply` with custom utilities sometimes breaks.
4. Replace `theme.extend` in your old config with `@theme` blocks in CSS.
## New Features Worth Using
### Container Queries
No more media queries for component-level responsiveness. Tailwind v4 ships container query utilities:
```html
<div class="@container">
<div class="grid @lg:grid-cols-2">...</div>
</div>
```
### Dynamic Utility Values
Arbitrary values are simpler: `w-(--sidebar-width)` references a CSS custom property. No more bracket syntax for common cases.
### Native Cascade Layers
Tailwind v4 uses `@layer` to control specificity. Base, components, and utilities are layered in the correct order — `@apply` in component layer no longer risks specificity wars.
## Gotchas
- Custom variants defined in old JS config need to be re-registered via `@variant` in CSS.
- The `important` config option now needs an explicit CSS strategy.
- Some plugins haven't updated yet — check compatibility before migrating production projects.
Overall, the migration took about two hours for a mid-sized project. The CSS-first approach feels more natural, and the build is noticeably faster thanks to the new Oxide engine.
-76
View File
@@ -1,76 +0,0 @@
---
title: "Deploying to AWS ECS with Terraform"
date: 2026-05-14T10:00:00+08:00
draft: false
poet: |
If you have built castles in the air,
your work need not be lost;
that is where they should be.
Now put the foundations under them.
— Henry David Thoreau, US, 1817–1862
description: "Infrastructure as code from scratch: VPC, subnets, security groups, ECR repository, ECS service with Fargate, and an ALB in front. Every resource explained."
tags:
- AWS
- Terraform
- DevOps
---
ECS with Fargate is the sweet spot between managing servers and going full serverless. Terraform makes it reproducible.
## The Stack
Here's what we need to provision:
| Resource | Purpose |
|----------|---------|
| VPC | Isolated network |
| Public & private subnets | Multi-AZ placement |
| Security groups | Network access control |
| ECR repository | Container image storage |
| ECS cluster + service | Run containers |
| ALB + target group | Traffic distribution |
## Security Groups: Getting Them Right
The key is getting the security groups right — one misconfigured rule and your containers can't talk to each other, or worse, your database is exposed to the internet.
```hcl
resource "aws_security_group" "ecs_service" {
name = "ecs-service-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 3000
to_port = 3000
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
```
The principle: **allow the minimum**. The ALB security group allows inbound from the internet on 80/443. The ECS security group only allows inbound from the ALB. The database security group only allows inbound from ECS.
## Fargate Configuration
Fargate abstracts the EC2 instances. You specify CPU and memory, and AWS handles the rest. For most web services, 0.25 vCPU / 512 MB is a good starting point — scale up based on load testing, not guessing.
## CI/CD Integration
After Terraform creates the infrastructure, your CI pipeline needs to:
1. Build and tag the Docker image
2. Push to ECR
3. Update the ECS service with the new task definition
Use a Terraform backend with state locking — S3 + DynamoDB is the standard approach. Without state locking, two people running `terraform apply` at the same time can corrupt your infrastructure state.
## Cost Notes
Fargate is more expensive per vCPU-hour than raw EC2, but you save the operational cost of patching instances and managing capacity. For small-to-medium workloads, the difference is negligible compared to the engineering time saved.
-47
View File
@@ -1,47 +0,0 @@
---
title: "我的效率工具链 2026"
date: 2026-05-12T18:00:00+08:00
draft: false
poet: |
磨刀不误砍柴工。
——中国谚语,中国
description: "折腾多年终于稳定下来的工具链。子弹日记做规划,Todoist 管任务,DeepSeek V4 当主力 AI,VS Code 写代码。选工具的原则就四个字:够用就好。"
tags:
- 工具
- 效率
- 推荐
---
持续折腾工具多年,今年终于稳定下来。记录一下目前的工具链,给想优化工作流的朋友参考。
## 笔记与知识管理
**子弹日记(纸笔)** — 每日规划和自我对话的核心载体。具体用法之前写过,不再重复。
**Hugo + Hextra** — 个人博客,用于对外输出。纯静态,零维护成本。
**GitHub** — 技术笔记和代码片段的存档。Markdown 文件 + 搜索,比任何笔记软件都好用。
## 任务管理
**Todoist** — 短期任务和提醒工具。优点是快速、跨平台、自然语言识别能力强。「今天要做的事」用它就够了。
## AI 工具
**DeepSeek V4** — 主力 AI 助手。Flash 模型日常用,Pro 模型处理复杂任务。API 接入各种场景。
## 开发相关
- **VS Code** — 主力编辑器
- **Hugo** — 静态博客生成器
- **Nginx** — Web 服务器
- **Git** — 版本控制
## 选工具的原则
1. **够用就好** — 不追求功能最全,追求用得顺手
2. **数据可控** — 优先选能导出、能自托管的方案
3. **学习成本低** — 花在学工具上的时间要能赚回来
4. **跨平台** — 手机和电脑都能用
好工具的标准不是功能多,而是让你忘记工具的存在,专注于事情本身。
-55
View File
@@ -1,55 +0,0 @@
---
title: "Vim Motions That Actually Save Time"
date: 2026-05-14T14:00:00+08:00
draft: false
poet: |
Practice does not make perfect.
Only perfect practice makes perfect.
— Vince Lombardi, US, 1913–1970
description: "Which Vim motions are worth the muscle memory investment? A practical three-tier ranking from non-negotiable (ci, %, dot) to nice-to-have (macros, jump list), based on three years of daily use."
tags:
- Vim
- Productivity
- Editor
---
Everyone tells you to learn Vim, but nobody tells you *which* motions are worth the muscle memory investment. After three years of daily use, here's my honest ranking.
## Tier 1: Non-Negotiable
These pay for themselves within a week:
| Motion | What it does | Why it matters |
|--------|-------------|----------------|
| `ci"` | Change inside quotes | Editing strings, attributes |
| `ci(` / `ci{` | Change inside brackets | Refactoring arguments |
| `%` | Jump to matching bracket | Navigating code blocks |
| `*` / `#` | Search word under cursor | Quick variable tracing |
| `.` | Repeat last change | The single biggest time-saver |
## Tier 2: Worth Practicing
These take a few weeks to internalize but compound:
- `f{char}` / `F{char}` — find character inline. Faster than `h`/`l` spam
- `t{char}` / `T{char}` — find *until* character. Perfect for deleting `until` a comma
- `ctrl+d` / `ctrl+u` — half-page scroll. Keeps your eyes on the same spot
- `zz` — center current line. Eliminates mental reorientation
## Tier 3: Nice to Have
Useful but not essential for daily work:
- `gt` / `gT` — switch tabs
- `ctrl+o` / `ctrl+i` — jump back/forward in the jumplist
- Macros (`q{register}`) — only worth it for repetitive tasks of 10+ iterations
## What I Don't Use
- **Line numbers as targets** (`:42`) — too slow mentally
- **Visual block mode** — I use multi-cursor in VS Code instead
- **`/` search with regex** — I just use `*` and `f` 90% of the time
---
The real productivity gain isn't in any single motion — it's in **not thinking about navigation**. When your fingers just move the cursor without conscious effort, that's when the payoff arrives.
-88
View File
@@ -1,88 +0,0 @@
---
title: "VPS 新手入门:从购买到上线一个网站"
date: 2026-05-12T19:00:00+08:00
draft: false
poet: |
路漫漫其修远兮,
吾将上下而求索。
——屈原,中国,约前340–前278
description: "买了一台云服务器之后怎么让它跑起来。从 SSH 登录、创建普通用户、配置密钥认证、设置 ufw 防火墙到用 Nginx 部署静态网站,一套完整的新手流程。"
tags:
- Linux
- VPS
- 教程
---
买了一台云服务器之后,怎么让它真正跑起来?这篇文章记录基本的 VPS 初始化和安全配置流程。
## 购买后的第一件事
拿到服务器 IP 和 root 密码后:
### 1. SSH 登录
```bash
ssh root@你的服务器IP
```
第一次登录会提示确认主机指纹,输入 `yes` 即可。
### 2. 创建普通用户
root 权限太大,日常操作应该用普通用户:
```bash
adduser 用户名
usermod -aG sudo 用户名
```
### 3. 配置 SSH 密钥登录
```bash
# 在本地机器上生成密钥
ssh-keygen -t ed25519
# 把公钥传到服务器
ssh-copy-id 用户名@服务器IP
```
然后编辑 `/etc/ssh/sshd_config`,关闭密码登录:
```
PasswordAuthentication no
```
### 4. 防火墙配置
用 ufw 简单配置:
```bash
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
```
### 5. 安装必要的软件
```bash
apt update && apt upgrade -y
apt install -y nginx curl wget git
```
## 部署静态网站
最简单的方式是用 Nginx:
1. 把构建好的静态文件放到 `/var/www/html` 或自定义目录
2. 配置 Nginx 站点文件指向该目录
3. 运行 `nginx -t && systemctl reload nginx`
## 安全底线
- 不要用 root 直接操作日常任务
- 关闭 SSH 密码登录
- 定期更新系统包
- 非必要不开放额外端口
服务器就像一间屋子,基础装修做好才能住得安心。