<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>流沙</title>
    <link>https://claspmoon.cn</link>
    <description>写代码，也写生活。</description>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 10 Oct 2026 03:35:33 GMT</lastBuildDate>
    <generator>VitePress</generator>
    <item>
      <title>笔记和教程的区别</title>
      <link>https://claspmoon.cn/posts/notes-vs-guides</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/notes-vs-guides</guid>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <description>我写了两百多篇笔记，真正能给别人看的不到二十篇。差别不在内容质量，在缺了三样东西。</description>
      <content:encoded><![CDATA[<h1 id="笔记和教程的区别" tabindex="-1">笔记和教程的区别 <a class="header-anchor" href="#笔记和教程的区别" aria-label="Permalink to &quot;笔记和教程的区别&quot;">&ZeroWidthSpace;</a></h1>
<p>翻自己两年前的笔记，经常遇到这种段落：</p>
<blockquote>
<p>这里要用 <code>--cap-add=SYS_ADMIN</code>，不然会报错。</p>
</blockquote>
<p>然后就没有了。报什么错？为什么需要这个权限？换台机器还行不行？</p>
<p><strong>我自己能看懂，因为写的时候我脑子里有完整上下文。但三个月后的我，已经变成了「别人」。</strong></p>
<p>这两年我慢慢摸清楚，笔记变成能给别人看的教程，差的不是内容质量，是三样东西。</p>
<h2 id="一、缺上下文" tabindex="-1">一、缺上下文 <a class="header-anchor" href="#一、缺上下文" aria-label="Permalink to &quot;一、缺上下文&quot;">&ZeroWidthSpace;</a></h2>
<p>笔记默认「我知道自己在说什么」。教程必须假设读者什么都不知道。</p>
<p>那行 <code>--cap-add=SYS_ADMIN</code>，补上上下文之后是这样：</p>
<blockquote>
<p>容器默认以受限权限运行。如果容器内需要挂载文件系统（比如跑一个 FUSE 程序），
内核会拒绝这个操作，报 <code>operation not permitted</code>。
<code>--cap-add=SYS_ADMIN</code> 把 <code>CAP_SYS_ADMIN</code> 这个 capability 加回给容器。
<strong>注意这是很大的权限</strong>，接近 root，只在你信任这个镜像时用。</p>
</blockquote>
<p>多出来的这几句，才是别人真正需要的东西。</p>
<h2 id="二、缺推导过程" tabindex="-1">二、缺推导过程 <a class="header-anchor" href="#二、缺推导过程" aria-label="Permalink to &quot;二、缺推导过程&quot;">&ZeroWidthSpace;</a></h2>
<p>笔记只记结论，因为推导过程当时在脑子里。</p>
<p>但结论是最容易过时的东西 —— 版本一升级，<code>--cap-add</code> 可能就换成别的写法了。
<strong>推导过程不会过时</strong>，它告诉你这个结论是为什么成立的，因此结论失效时你知道该往哪找替代方案。</p>
<p>所以教程里我尽量写「因为 A 所以 B」，而不是直接给 B。</p>
<h2 id="三、缺可复现的步骤" tabindex="-1">三、缺可复现的步骤 <a class="header-anchor" href="#三、缺可复现的步骤" aria-label="Permalink to &quot;三、缺可复现的步骤&quot;">&ZeroWidthSpace;</a></h2>
<p>笔记里写「先装个依赖」，教程里必须写清楚是哪个版本、用什么命令装。</p>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 不是这样</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> docker</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 而是这样</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> docker.io</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">systemctl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> enable</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --now</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> docker</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --version</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # 期望输出：Docker version 24.x</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>给出<strong>期望输出</strong>特别重要。读者跑到这一步发现输出不一样，就知道自己走岔了，
而不是带着错误继续往下跑。</p>
<h2 id="那笔记还有价值吗" tabindex="-1">那笔记还有价值吗 <a class="header-anchor" href="#那笔记还有价值吗" aria-label="Permalink to &quot;那笔记还有价值吗&quot;">&ZeroWidthSpace;</a></h2>
<p>有，但价值不一样。</p>
<p>笔记的价值是<strong>当时的我写给当时的我</strong>，它的作用是记录「我做过这件事、结论是什么」。
它的读者只有一个，而且那个读者当时就在现场。</p>
<p>教程的价值是<strong>跨越时间的传递</strong>。它必须能在没有我在场的情况下独立成立。</p>
<p>所以现在我的做法是分开：</p>
<ul>
<li>随手记的东西放本地笔记软件，不打算给别人看，怎么省事怎么写</li>
<li>一个主题想清楚了、验证过两遍以上，才整理成教程发布</li>
</ul>
<p>判断标准很简单：<strong>如果我不能在半年后只看这篇文字就把它重做一遍，那它就还只是笔记。</strong></p>
<h2 id="一个副作用" tabindex="-1">一个副作用 <a class="header-anchor" href="#一个副作用" aria-label="Permalink to &quot;一个副作用&quot;">&ZeroWidthSpace;</a></h2>
<p>把笔记整理成教程之后，我发现自己对技术的理解变了。</p>
<p>写笔记时我是在记录「怎么用」，整理教程时被迫回答「为什么是这样」。
好几个我以为自己懂的地方，在试图向别人解释的时候才发现是空的。</p>
<p>这可能才是整理教程最大的收益 —— 不是为了读者，是为了确认自己真的懂了。</p>
]]></content:encoded>
    </item>
    <item>
      <title>用 Docker + Caddy 部署一个只属于自己的博客</title>
      <link>https://claspmoon.cn/posts/docker-caddy-deploy</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/docker-caddy-deploy</guid>
      <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
      <description>从一台干净的 VPS 开始，把域名、HTTPS、自动部署串起来，全程不超过 30 分钟。</description>
      <content:encoded><![CDATA[<p>从一台干净的 VPS 开始，把域名、HTTPS、自动部署串起来，全程不超过 30 分钟。</p>
<h2 id="为什么是-caddy-而不是-nginx" tabindex="-1">为什么是 Caddy 而不是 Nginx <a class="header-anchor" href="#为什么是-caddy-而不是-nginx" aria-label="Permalink to &quot;为什么是 Caddy 而不是 Nginx&quot;">&ZeroWidthSpace;</a></h2>
<p>Nginx 很强，但配 HTTPS 要额外装 certbot、写续期定时任务、还得记得 <code>nginx -s reload</code>。
Caddy 把这三件事合成了一件：<strong>写个域名，它自己去申请证书、自己去续、自己重载</strong>。</p>
<p>对一个个人博客来说，这就是全部的理由。</p>
<h2 id="第一步-域名解析" tabindex="-1">第一步：域名解析 <a class="header-anchor" href="#第一步-域名解析" aria-label="Permalink to &quot;第一步：域名解析&quot;">&ZeroWidthSpace;</a></h2>
<p>在你的域名商后台加一条 A 记录：</p>
<table tabindex="0">
<thead>
<tr>
<th>类型</th>
<th>主机记录</th>
<th>记录值</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>blog</td>
<td>你的服务器 IP</td>
</tr>
</tbody>
</table>
<p>等几分钟让解析生效，用 <code>dig blog.example.com +short</code> 确认能查到 IP。</p>
<h2 id="第二步-caddyfile" tabindex="-1">第二步：Caddyfile <a class="header-anchor" href="#第二步-caddyfile" aria-label="Permalink to &quot;第二步：Caddyfile&quot;">&ZeroWidthSpace;</a></h2>
<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>blog.example.com {</span></span>
<span class="line"><span>    root * /srv/blog</span></span>
<span class="line"><span>    encode zstd gzip</span></span>
<span class="line"><span></span></span>
<span class="line"><span>    try_files {path} {path}.html {path}/index.html /404.html</span></span>
<span class="line"><span>    file_server</span></span>
<span class="line"><span></span></span>
<span class="line"><span>    @assets path /assets/*</span></span>
<span class="line"><span>    header @assets Cache-Control "public, max-age=31536000, immutable"</span></span>
<span class="line"><span>}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>几个容易踩的点：</p>
<ul>
<li><code>try_files</code> 那行是必须的。VitePress 开了 <code>cleanUrls</code> 之后，<code>/posts/hello</code> 实际对应的是
<code>posts/hello.html</code>，不加这行访问文章页会 404。</li>
<li>带 hash 的静态资源（<code>/assets/xxx.abc123.js</code>）可以放心设一年缓存，因为文件名变了内容才变。</li>
<li><code>encode zstd gzip</code> 能让 HTML 传输体积再小一截。</li>
</ul>
<h2 id="第三步-docker-compose" tabindex="-1">第三步：docker-compose <a class="header-anchor" href="#第三步-docker-compose" aria-label="Permalink to &quot;第三步：docker-compose&quot;">&ZeroWidthSpace;</a></h2>
<div class="language-yaml vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">services</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  web</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    image</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">caddy:2-alpine</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    restart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">unless-stopped</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    ports</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"80:80"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"443:443"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./Caddyfile:/etc/caddy/Caddyfile:ro</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./dist:/srv/blog:ro</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">caddy_data:/data</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">caddy_config:/config</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  caddy_data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  caddy_config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p><code>caddy_data</code> 这个卷<strong>一定要持久化</strong>，证书就存在里面。丢了的话重启后会重新申请，
Let's Encrypt 有频率限制，短时间内反复申请会被限流。</p>
<h2 id="第四步-验证" tabindex="-1">第四步：验证 <a class="header-anchor" href="#第四步-验证" aria-label="Permalink to &quot;第四步：验证&quot;">&ZeroWidthSpace;</a></h2>
<div class="language-bash vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> up</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">docker</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> compose</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> logs</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -f</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> web</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>看到类似 <code>certificate obtained successfully</code> 就说明证书签下来了。</p>
<blockquote>
<p>如果一直卡在申请证书，先检查 80 端口有没有被占用 —— Caddy 申请证书要用 80 端口做 HTTP 校验。</p>
</blockquote>
<h2 id="自动化部署" tabindex="-1">自动化部署 <a class="header-anchor" href="#自动化部署" aria-label="Permalink to &quot;自动化部署&quot;">&ZeroWidthSpace;</a></h2>
<p>手动 <code>rsync</code> 传文件能跑通之后，就该交给 CI 了。我的做法是：</p>
<ol>
<li>本地写完 <code>git push</code></li>
<li>GitHub Actions 自动构建</li>
<li><code>rsync</code> 把 <code>dist/</code> 同步到服务器</li>
</ol>
<p>服务器上只跑 Caddy，不需要 Node，也不需要构建环境。这样即使 CI 挂了，
站点本身也完全不受影响。</p>
]]></content:encoded>
    </item>
    <item>
      <title>我为什么放弃了 Medium</title>
      <link>https://claspmoon.cn/posts/why-i-left-medium</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/why-i-left-medium</guid>
      <pubDate>Sat, 12 Sep 2026 00:00:00 GMT</pubDate>
      <description>平台会消失，链接会失效，但一个自己的域名可以陪你很久很久。</description>
      <content:encoded><![CDATA[<p>平台会消失，链接会失效，但一个自己的域名可以陪你很久很久。</p>
<h2 id="一开始它真的很好" tabindex="-1">一开始它真的很好 <a class="header-anchor" href="#一开始它真的很好" aria-label="Permalink to &quot;一开始它真的很好&quot;">&ZeroWidthSpace;</a></h2>
<p>2019 年我在 Medium 上写第一篇文章，体验是惊艳的：干净的编辑器、不用管排版、
点一下就能发出去，还有一堆人给你鼓掌。</p>
<p>那时候我觉得「专注写作」这件事终于被解决了。</p>
<h2 id="然后它慢慢变了" tabindex="-1">然后它慢慢变了 <a class="header-anchor" href="#然后它慢慢变了" aria-label="Permalink to &quot;然后它慢慢变了&quot;">&ZeroWidthSpace;</a></h2>
<p>先是阅读量开始往下掉。后来发现是付费墙 —— 我的文章被圈进了会员内容，
读者点进来只能看到两段。我从来没同意过这件事。</p>
<p>再后来是推荐流。首页推的东西和我关注的人越来越没关系，写文章的动力变成了
「怎么才能被算法喜欢」。</p>
<h2 id="最要命的是链接" tabindex="-1">最要命的是链接 <a class="header-anchor" href="#最要命的是链接" aria-label="Permalink to &quot;最要命的是链接&quot;">&ZeroWidthSpace;</a></h2>
<p>我做过一次统计：三年里发的 47 篇文章，有 6 篇因为平台改版或者账号问题打不开了。</p>
<p>六年之后呢？十年之后呢？</p>
<p>Medium 不是第一个消失的内容平台，也不会是最后一个。<strong>每一次平台消失，
都会带走一批本来可以留下来的文字。</strong></p>
<h2 id="现在我的做法" tabindex="-1">现在我的做法 <a class="header-anchor" href="#现在我的做法" aria-label="Permalink to &quot;现在我的做法&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>文章以 Markdown 存在自己的 git 仓库里</li>
<li>构建成一个纯静态站点，跑在自己的 VPS 上</li>
<li>域名是我自己的，换服务器只要改一条 A 记录</li>
</ul>
<p>成本是一年几十块钱的服务器，加上一个下午的配置时间。</p>
<p>换来的是：<strong>只要我还愿意付这个钱，这些字就一直在。</strong></p>
<h2 id="一些实际的收益" tabindex="-1">一些实际的收益 <a class="header-anchor" href="#一些实际的收益" aria-label="Permalink to &quot;一些实际的收益&quot;">&ZeroWidthSpace;</a></h2>
<p>写完上面那些「情怀」的部分，说说很实际的东西：</p>
<ol>
<li><strong>想改就改。</strong> 三年前的文章发现写错了，直接改，改完立刻生效。</li>
<li><strong>没有编辑器绑架。</strong> 用 Vim、VS Code、Typora 都行，就是普通文本文件。</li>
<li><strong>数据是自己的。</strong> 想看访问统计就自己装一个，不想装就什么都没有，没人追踪读者。</li>
<li><strong>能玩。</strong> 想加个交互式的图表、想在文章里跑一段代码，都没人拦着你。</li>
</ol>
<blockquote>
<p>如果你也在犹豫，我的建议是：不用急着搬。先在自建站点上发新文章，
老文章慢慢搬。半年之后你自然会知道哪个更舒服。</p>
</blockquote>
]]></content:encoded>
    </item>
    <item>
      <title>Rust 所有权：一份写给自己的笔记</title>
      <link>https://claspmoon.cn/posts/rust-ownership-notes</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/rust-ownership-notes</guid>
      <pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate>
      <description>借用检查器不是敌人，它只是比我更早地发现了问题。</description>
      <content:encoded><![CDATA[<p>借用检查器不是敌人，它只是比我更早地发现了问题。</p>
<h2 id="三条规则-一句话" tabindex="-1">三条规则，一句话 <a class="header-anchor" href="#三条规则-一句话" aria-label="Permalink to &quot;三条规则，一句话&quot;">&ZeroWidthSpace;</a></h2>
<p>Rust 所有权的规则只有三条：</p>
<ol>
<li>每个值都有一个所有者</li>
<li>同一时刻只能有一个所有者</li>
<li>所有者离开作用域时，值被丢弃</li>
</ol>
<p>看起来简单，真正让人卡住的是「借用」和「生命周期」这两层。</p>
<h2 id="移动-move-到底发生了什么" tabindex="-1">移动（move）到底发生了什么 <a class="header-anchor" href="#移动-move-到底发生了什么" aria-label="Permalink to &quot;移动（move）到底发生了什么&quot;">&ZeroWidthSpace;</a></h2>
<div class="language-rust vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">rust</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> s1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> String</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> s2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> s1;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">println!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"{}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, s1); </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 编译错误：borrow of moved value</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>很多人第一反应是「这不是浅拷贝吗」。不完全是。</p>
<p><code>String</code> 在栈上存的是「指针 + 长度 + 容量」，真实字符数据在堆上。
赋值时 Rust 把栈上那三个字段复制过去，<strong>同时把 <code>s1</code> 标记为失效</strong>。</p>
<p>所以它不是浅拷贝（那样会导致双重释放），也不是深拷贝（那样有运行时开销），
而是<strong>移动</strong>：所有权转移，旧变量作废。</p>
<blockquote>
<p>想保留原来的变量，用 <code>s1.clone()</code>，但要清楚这是显式付出了一次堆分配的成本。</p>
</blockquote>
<h2 id="借用-把「读」和「写」分开" tabindex="-1">借用：把「读」和「写」分开 <a class="header-anchor" href="#借用-把「读」和「写」分开" aria-label="Permalink to &quot;借用：把「读」和「写」分开&quot;">&ZeroWidthSpace;</a></h2>
<p>借用规则可以概括成一句话：</p>
<p><strong>要么有任意多个不可变借用，要么有恰好一个可变借用，两者不能同时存在。</strong></p>
<div class="language-rust vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">rust</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> mut</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> vec!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> a </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v;      </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 不可变借用</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> b </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">v;      </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 再来一个，没问题</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">println!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"{a:?} {b:?}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);   </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// a、b 在这里之后就不再使用</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">let</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> c </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;mut</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v;  </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// 现在可以可变借用了</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">c</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">push</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>关键在最后一段：<code>a</code> 和 <code>b</code> 在 <code>println!</code> 之后就<strong>再也没有被使用</strong>，
所以它们的借用生命周期在那一行结束了。这就是所谓的 NLL（非词法生命周期）。</p>
<p>初学者最常犯的错是以为「借用会持续到作用域结束」，实际上编译器看的是
<strong>最后一次使用的位置</strong>。</p>
<h2 id="什么时候该用-rc-和-refcell" tabindex="-1">什么时候该用 Rc 和 RefCell <a class="header-anchor" href="#什么时候该用-rc-和-refcell" aria-label="Permalink to &quot;什么时候该用 Rc 和 RefCell&quot;">&ZeroWidthSpace;</a></h2>
<p>如果你发现自己在跟借用检查器较劲，先别急着上 <code>Rc&lt;RefCell&lt;T&gt;&gt;</code>，问自己三个问题：</p>
<table tabindex="0">
<thead>
<tr>
<th>问题</th>
<th>如果是</th>
<th>该用</th>
</tr>
</thead>
<tbody>
<tr>
<td>真的需要共享所有权吗？</td>
<td>是</td>
<td><code>Rc&lt;T&gt;</code> / <code>Arc&lt;T&gt;</code></td>
</tr>
<tr>
<td>真的需要在共享的同时修改吗？</td>
<td>是</td>
<td><code>Rc&lt;RefCell&lt;T&gt;&gt;</code></td>
</tr>
<tr>
<td>这个结构真的需要是图吗？</td>
<td>否</td>
<td>重新设计数据布局</td>
</tr>
</tbody>
</table>
<p>我的经验是：<strong>大部分时候答案是「不需要」</strong>。把数据拆开、把所有权理清楚，
代码往往比堆一层 <code>RefCell</code> 更清楚。</p>
<h2 id="一点感想" tabindex="-1">一点感想 <a class="header-anchor" href="#一点感想" aria-label="Permalink to &quot;一点感想&quot;">&ZeroWidthSpace;</a></h2>
<p>写了几个月 Rust 之后，最大的收获不是学会了一门语言，
而是被迫把「这块内存归谁管」这件事想清楚了。</p>
<p>以前写 C++ 或者 Go，这些决定是隐式的，靠习惯和约定。
Rust 把它们摆到台面上，编译不过的时候你就得想明白。</p>
<p>想明白了，代码通常也就变简单了。</p>
]]></content:encoded>
    </item>
    <item>
      <title>东京四日：一些照片和碎念</title>
      <link>https://claspmoon.cn/posts/tokyo-four-days</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/tokyo-four-days</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>雨天的神保町，旧书店二楼，一杯放凉了的咖啡。</description>
      <content:encoded><![CDATA[<p>雨天的神保町，旧书店二楼，一杯放凉了的咖啡。</p>
<h2 id="第一天-到达" tabindex="-1">第一天：到达 <a class="header-anchor" href="#第一天-到达" aria-label="Permalink to &quot;第一天：到达&quot;">&ZeroWidthSpace;</a></h2>
<p>落地的时候在下雨。成田到市区坐了一个多小时的 Skyliner，
窗外的房子一栋接一栋地贴在一起，招牌都是竖着的。</p>
<p>酒店房间小得有点好笑 —— 行李箱打开之后就没法走路了。
但窗户正对着一栋居民楼，晚上能看到对面阳台晾着的衣服和几盆绿植。</p>
<p>那一刻忽然觉得，比起景点，我好像更喜欢看别人怎么过日子。</p>
<h2 id="第二天-神保町" tabindex="-1">第二天：神保町 <a class="header-anchor" href="#第二天-神保町" aria-label="Permalink to &quot;第二天：神保町&quot;">&ZeroWidthSpace;</a></h2>
<p>本来只打算逛两小时，结果待了一整个下午。</p>
<p>神保町的书店密度高得离谱，一条街走过去能看到十几家。
大部分是旧书店，门口堆着 100 日元一本的文库本，店主坐在里面看报纸。</p>
<p>在三省堂二楼找到一本 1970 年代的摄影集，讲的是当时的下町。
纸张已经泛黄，但照片的层次感很好。翻了很久，最后没买 —— 太重了。</p>
<blockquote>
<p>后来有点后悔。下次去大概会买。</p>
</blockquote>
<h2 id="第三天-雨停了" tabindex="-1">第三天：雨停了 <a class="header-anchor" href="#第三天-雨停了" aria-label="Permalink to &quot;第三天：雨停了&quot;">&ZeroWidthSpace;</a></h2>
<p>去了清澄白河。那边有几家咖啡烘焙坊，都是仓库改的，层高很高。</p>
<p>在一家店里坐了三个小时，看完了半本书。
旁边桌是个在写论文的女生，桌上摊着两台电脑和一堆打印出来的资料。</p>
<p>出门的时候天晴了，路面还是湿的，反着光。</p>
<h2 id="第四天-回程" tabindex="-1">第四天：回程 <a class="header-anchor" href="#第四天-回程" aria-label="Permalink to &quot;第四天：回程&quot;">&ZeroWidthSpace;</a></h2>
<p>早上五点半起床，赶第一班地铁去机场。</p>
<p>地铁上空荡荡的，只有几个穿西装的人和两个拖着箱子的旅客。
车厢里的广告还没换，是昨天那批。</p>
<p>在机场买了两个饭团，坐在登机口旁边的椅子上吃完。
飞机起飞的时候，从窗户往下看，整个城市是一格一格的灰。</p>
<h2 id="记一些细节" tabindex="-1">记一些细节 <a class="header-anchor" href="#记一些细节" aria-label="Permalink to &quot;记一些细节&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>便利店的饭团比想象中好吃，尤其是明太子的</li>
<li>自动贩卖机真的到处都是，而且真的什么都有</li>
<li>下雨天没带伞也不用慌，便利店 500 日元一把</li>
<li>大部分店只收现金，别像我一样到了才发现</li>
</ul>
<p>下次想去的季节是秋天，听说银杏会黄。</p>
]]></content:encoded>
    </item>
    <item>
      <title>把笔记搬进 git 之后，我终于开始复读了</title>
      <link>https://claspmoon.cn/posts/notes-in-git</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/notes-in-git</guid>
      <pubDate>Wed, 22 Jul 2026 00:00:00 GMT</pubDate>
      <description>换过七个笔记软件之后我才明白，问题不在工具，在于我从来没回去看过。</description>
      <content:encoded><![CDATA[<p>换过七个笔记软件之后我才明白，问题不在工具，在于我从来没回去看过。</p>
<h2 id="换过的那些" tabindex="-1">换过的那些 <a class="header-anchor" href="#换过的那些" aria-label="Permalink to &quot;换过的那些&quot;">&ZeroWidthSpace;</a></h2>
<p>印象笔记、Notion、Obsidian、语雀、飞书文档、Apple Notes、以及一个自己写的
纯文本 + grep 的方案。</p>
<p>每一个都用了至少三个月。每一个都在某个时刻让我觉得「这次对了」。</p>
<h2 id="真正的问题" tabindex="-1">真正的问题 <a class="header-anchor" href="#真正的问题" aria-label="Permalink to &quot;真正的问题&quot;">&ZeroWidthSpace;</a></h2>
<p>去年整理硬盘的时候，我导出了所有笔记平台的备份，放在一起看：</p>
<ul>
<li>印象笔记 400 多篇，最后修改时间集中在 2018 年</li>
<li>Notion 200 多篇，一半是各种模板和看板</li>
<li>Obsidian 100 多篇，双链画得挺漂亮</li>
</ul>
<p>加起来 700 多篇。<strong>我真正回头读过的大概不到 20 篇。</strong></p>
<p>问题从来不是「哪个软件更好」，而是「我写完就不看了」。</p>
<h2 id="现在的做法" tabindex="-1">现在的做法 <a class="header-anchor" href="#现在的做法" aria-label="Permalink to &quot;现在的做法&quot;">&ZeroWidthSpace;</a></h2>
<p>规则很简单：</p>
<ol>
<li>所有笔记是 <code>.md</code> 文件，放在一个 git 仓库里</li>
<li>目录就是分类，不搞标签体系</li>
<li>每次要查东西，先 <code>grep -r &quot;关键词&quot; .</code></li>
<li>每周五花二十分钟，随便翻翻这周改过什么</li>
</ol>
<p>第 4 条是关键。以前我也定过「每周回顾」的计划，但那时候笔记散在云上，
回顾的成本是「打开 App、等同步、翻列表」。现在是 <code>cd notes &amp;&amp; git log --since=1.week</code>，
一条命令。</p>
<h2 id="一些副作用" tabindex="-1">一些副作用 <a class="header-anchor" href="#一些副作用" aria-label="Permalink to &quot;一些副作用&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>开始写得更短了。反正要复读，写得啰嗦自己受罪</li>
<li>开始删东西了。看到三年前的废话，顺手就删了</li>
<li>搜索变快了。<code>grep</code> 比任何笔记软件的搜索都快</li>
</ul>
<p>工具确实重要，但它解决的问题是「查找」，不是「回顾」。
回顾得靠一个能坚持下去的习惯 —— 而习惯需要摩擦足够小。</p>
]]></content:encoded>
    </item>
    <item>
      <title>我用 Caddy 换掉了用了六年的 Nginx</title>
      <link>https://claspmoon.cn/posts/caddy-vs-nginx</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/caddy-vs-nginx</guid>
      <pubDate>Sun, 05 Jul 2026 00:00:00 GMT</pubDate>
      <description>不是因为 Nginx 不好，而是因为我不想再为「证书续期」这件事操心了。</description>
      <content:encoded><![CDATA[<p>不是因为 Nginx 不好，而是因为我不想再为「证书续期」这件事操心了。</p>
<h2 id="那件事" tabindex="-1">那件事 <a class="header-anchor" href="#那件事" aria-label="Permalink to &quot;那件事&quot;">&ZeroWidthSpace;</a></h2>
<p>每年总有那么一两次，我会在某个早上收到浏览器的大红警告，
然后想起来：哦，证书过期了。</p>
<p>原因每次都差不多 —— certbot 的续期任务失败了，但我没看邮件。
失败的原因也五花八门：DNS 临时解析不了、<code>webroot</code> 路径被改了、
某个服务占了 80 端口、或者单纯是 systemd timer 没触发。</p>
<p>六年里大概发生过四五次。每次修好要二十分钟，
但那种「随时可能挂」的感觉一直在。</p>
<h2 id="换过来之后" tabindex="-1">换过来之后 <a class="header-anchor" href="#换过来之后" aria-label="Permalink to &quot;换过来之后&quot;">&ZeroWidthSpace;</a></h2>
<p>Caddyfile 里写的就一行：</p>
<div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>example.com {</span></span>
<span class="line"><span>    root * /srv</span></span>
<span class="line"><span>    file_server</span></span>
<span class="line"><span>}</span></span></code></pre>
<div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>第一次启动它会去申请证书，之后每 60 天自动续期，
续完自己 reload，不需要任何定时任务。</p>
<p>我已经跑了一年多，没有收到过一次证书警告。</p>
<h2 id="性能上有区别吗" tabindex="-1">性能上有区别吗 <a class="header-anchor" href="#性能上有区别吗" aria-label="Permalink to &quot;性能上有区别吗&quot;">&ZeroWidthSpace;</a></h2>
<p>我的场景下没有可测量的区别。都是静态文件服务，
Caddy 的 HTTP/2 和 HTTP/3 是默认开的，Nginx 需要额外配置。</p>
<p>如果做反向代理扛高并发，Nginx 的调优空间确实更大。
但个人站点的瓶颈从来不在 Web 服务器上。</p>
<h2 id="什么时候我还是会用-nginx" tabindex="-1">什么时候我还是会用 Nginx <a class="header-anchor" href="#什么时候我还是会用-nginx" aria-label="Permalink to &quot;什么时候我还是会用 Nginx&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>需要非常精细的 <code>location</code> 匹配和 <code>rewrite</code> 规则</li>
<li>团队里所有人都熟悉 Nginx，换掉的学习成本不划算</li>
<li>需要一些只有 Nginx 模块才有的功能（比如某些 WAF 集成）</li>
</ul>
<h2 id="一句话总结" tabindex="-1">一句话总结 <a class="header-anchor" href="#一句话总结" aria-label="Permalink to &quot;一句话总结&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>Caddy 用一点灵活性，换掉了整整一类运维事故。</strong>
对我这种一个人维护几个小站点的人来说，这笔交易很划算。</p>
]]></content:encoded>
    </item>
    <item>
      <title>2026 年过半，我的阅读清单</title>
      <link>https://claspmoon.cn/posts/reading-list-2026-h1</link>
      <guid isPermaLink="true">https://claspmoon.cn/posts/reading-list-2026-h1</guid>
      <pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate>
      <description>上半年读了 11 本，其中 3 本值得专门写一写。</description>
      <content:encoded><![CDATA[<p>上半年读了 11 本，其中 3 本值得专门写一写。</p>
<h2 id="《置身事内》" tabindex="-1">《置身事内》 <a class="header-anchor" href="#《置身事内》" aria-label="Permalink to &quot;《置身事内》&quot;">&ZeroWidthSpace;</a></h2>
<p>讲中国地方政府的经济逻辑。最大的收获不是某个具体结论，
而是终于理解了「土地财政」这套东西是怎么转起来的。</p>
<p>书里有一句话印象很深：<strong>「钱的流向，比任何口号都更能说明问题。」</strong></p>
<p>读完之后再看新闻里那些基建、招商、债务的报道，感觉完全不一样了。</p>
<h2 id="《我们仨》" tabindex="-1">《我们仨》 <a class="header-anchor" href="#《我们仨》" aria-label="Permalink to &quot;《我们仨》&quot;">&ZeroWidthSpace;</a></h2>
<p>杨绛写钱锺书和钱瑗。</p>
<p>一开始以为是本温暖的家庭回忆录，读到中间才发现是写失去的。
三个人走散了，只剩下一个人在原地等。</p>
<p>语言极其克制，几乎没有一句直接写「我很难过」，
但每一段都在写这件事。看完之后我坐了很久没动。</p>
<h2 id="《designing-data-intensive-applications》" tabindex="-1">《Designing Data-Intensive Applications》 <a class="header-anchor" href="#《designing-data-intensive-applications》" aria-label="Permalink to &quot;《Designing Data-Intensive Applications》&quot;">&ZeroWidthSpace;</a></h2>
<p>这本是技术书，但读起来像在读一部长篇论证。</p>
<p>它不讲「怎么用某个数据库」，而是讲<strong>为什么会有这些数据库</strong>：
分布式系统里那些根本性的权衡 —— 一致性、可用性、分区容忍，
以及它们各自要付出什么代价。</p>
<p>读完最大的变化是：以前选技术栈靠「大家都用这个」，
现在会先问「我的场景里哪个代价是可以接受的」。</p>
<h2 id="没读完的" tabindex="-1">没读完的 <a class="header-anchor" href="#没读完的" aria-label="Permalink to &quot;没读完的&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>《尤利西斯》—— 第三次失败，可能真的不适合我</li>
<li>《人类简史》—— 读了三分之一，觉得论述有点跳跃</li>
<li>一本讲 Kubernetes 内部原理的，太厚了，当作工具书在查</li>
</ul>
<h2 id="下半年想读的" tabindex="-1">下半年想读的 <a class="header-anchor" href="#下半年想读的" aria-label="Permalink to &quot;下半年想读的&quot;">&ZeroWidthSpace;</a></h2>
<ol>
<li>《贫穷的本质》</li>
<li>《The Staff Engineer's Path》</li>
<li>《置身事内》作者的另一本</li>
</ol>
<p>如果有什么推荐，欢迎写信告诉我。</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
