<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://guoxin.wiki/</id>
  <title type="text">Guoxin Wiki</title>
  <subtitle type="text">工作、思考与生活记录</subtitle>
  <updated>2026-10-21T00:00:00.000Z</updated>
  <author><name>Guoxin</name></author>
  <link rel="alternate" href="https://guoxin.wiki/"/>
  <link rel="self" href="https://guoxin.wiki/atom.xml"/>
  <generator uri="https://github.com/CuteLeaf/Firefly">Firefly v6.16.8</generator>
    <entry>
      <id>https://guoxin.wiki/posts/claude-egress-block-win11/</id>
      <title type="text">Windows 11 上封锁 Claude Code 出网：防火墙 + DNS + hosts 三层实战</title>
      <published>2026-10-21T00:00:00.000Z</published>
      <updated>2026-10-21T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/claude-egress-block-win11/"/>
      <summary type="text">用防火墙规则、DNS 重定向和 hosts 三层手段封锁 Claude Code 的出网流量，并给出一套可验证、可回滚的完整脚本与自检流程。</summary>
      <content type="html"><![CDATA[<blockquote><p>适用机器：Windows 11（build 26200，x64）+ WSL2 Ubuntu-24.04 + Docker Desktop + Clash Verge<br />
适用场景：本机跑 Claude Code / CPA / 浏览器，只有走代理才能连 Anthropic，直连必须死<br />
对应服务器版：同目录 <code>CLAUDE-EGRESS-BLOCK-TUTORIAL.md</code><br />
最后更新：2026-10-22</p></blockquote>
<hr />
<section><h2>0. 目标与效果<a href="#0-目标与效果"><span>#</span></a></h2><p>目标是让本机上的任何进程：</p><ul>
<li>无法直接连接 Anthropic / Claude 官方域名和 IP（主机 / WSL2 / Docker Desktop 容器全覆盖）；</li>
<li>只能通过本机 Clash 代理访问；</li>
<li>代理崩溃或配置出错时请求直接失败，<strong>绝不回落到直连</strong>；</li>
<li>重启后规则、DNS 仍然生效。</li>
</ul><p>最终效果（2026-10-22 实测）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>主机 IPv4 直连 Anthropic 网段            -&gt; 防火墙内核层丢弃</span></div></div><div><div><div>2</div></div><div><span>主机 IPv6 直连 Anthropic 网段            -&gt; 防火墙内核层丢弃</span></div></div><div><div><div>3</div></div><div><span>WSL2 (Ubuntu-24.04) 直连                 -&gt; nftables 丢弃（双保险）</span></div></div><div><div><div>4</div></div><div><span>Docker Desktop 容器直连                  -&gt; Windows 防火墙出站规则同样生效（替身实测覆盖）</span></div></div><div><div><div>5</div></div><div><span>通过 Clash 代理                          -&gt; 不受影响（代理节点 IP 不在封锁集合内）</span></div></div><div><div><div>6</div></div><div><span>Clash 停止时直连                         -&gt; 仍然必死</span></div></div><div><div><div>7</div></div><div><span>重启后                                   -&gt; 防火墙规则持久 + WSL systemd 自启</span></div></div></code></pre><div><div></div><div></div></div></figure></div><blockquote><p>验证分两阶段：阶段一<strong>全程零 Anthropic 流量</strong>（替身 IP 223.5.5.5 + 中性域名 baidu.com）；
阶段二端到端不连通实测已于 2026-10-22 执行通过，结果见第 7 节。</p></blockquote><hr /></section>
<section><h2>1. 原理：三层防线与 Windows 特有的坑<a href="#1-原理三层防线与-windows-特有的坑"><span>#</span></a></h2><p>服务器版三层（DNS 纠正 + Clash 显式规则 + nftables）在 Windows 上的对应：</p>

<table><thead><tr><th>服务器层</th><th>Windows 对应</th><th>说明</th></tr></thead><tbody><tr><td>nftables <code>output</code> 链</td><td>Windows Defender Firewall 出站规则（WFP 层）</td><td><code>New-NetFirewallRule</code>，按目的 IP 封，写入策略库、重启持久</td></tr><tr><td>nftables <code>forward</code> 链</td><td>同上（实测覆盖 Docker Desktop NAT 流量）</td><td>WSL 内再部署一套 nftables 双保险</td></tr><tr><td>netplan 公网 DNS</td><td><code>Set-DnsClientServerAddress</code></td><td>大陆家宽用 223.5.5.5 / 119.29.29.29，<strong>不要照抄服务器版的 1.1.1.1 / 8.8.8.8</strong>（大陆不可靠）</td></tr><tr><td>Clash 显式规则</td><td>Clash Verge 中 anthropic/claude 域名 → 代理组</td><td>保证”走代理可用”</td></tr><tr><td>systemd 开机顺序</td><td>防火墙规则本身持久；WSL 用 systemd 单元</td><td>无需额外开机脚本</td></tr></tbody></table><p>Windows 特有的坑（本次实测/踩坑记录）：</p><ol>
<li><strong>PowerShell 5.1 把无 BOM 的 UTF-8 脚本按 GBK 解析</strong>。<code>.ps1</code> 里出现中文（例如 <code>'以太网'</code>）会直接 ParserError，症状：UAC 点了”是”、日志没生成、提权窗口一闪而过。<strong>所有提权脚本必须纯 ASCII</strong>；网卡用 <code>InterfaceDescription</code> 过滤，不要写本地化网卡名。</li>
<li><strong>DoH 绕过 DNS/hosts</strong>：Chrome/Edge Secure DNS 不走系统 DNS。DNS/hosts 只是辅助层，最终保证是 IP 层封锁。</li>
<li><strong>IPv6 必须一起封</strong>（2607:6bc0::/32）：Windows 优先走 v6。</li>
<li><strong>WSL2 / Docker Desktop 走 NAT 转发路径</strong>，理论上 Windows 防火墙出站规则（ALE 层）只管本机进程；但本次替身实测证明 Docker Desktop 容器流量<strong>实际被覆盖</strong>（见 6.2）。WSL 内仍按服务器方案部署 nftables 做双保险。</li>
<li><strong>hosts 是”失败安全”方向</strong>：将来若开 Clash TUN 模式，hosts 会让这些域名连代理路径一起报错（表现为连接失败，而非直连）。届时删掉 hosts 段即可，IP 层封锁仍在。</li>
</ol><hr /></section>
<section><h2>2. 前置检查<a href="#2-前置检查"><span>#</span></a></h2><p>在本机执行（全部只查本地状态，不连 Anthropic）：</p><div><div><div><figure><figcaption><span></span><span>Terminal window</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 提权状态与管理员组成员</span></div></div><div><div><div>2</div></div><div><span>([</span><span>Security.Principal.WindowsPrincipal</span><span>][</span><span>Security.Principal.WindowsIdentity</span><span>]::GetCurrent()).IsInRole([</span><span>Security.Principal.WindowsBuiltInRole</span><span>]::Administrator)</span></div></div><div><div><div>3</div></div><div><span>Get-LocalGroupMember</span><span><span> </span><span>-</span><span>Group Administrators</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 现有防火墙规则（应为空）</span></div></div><div><div><div>6</div></div><div><span>Get-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>"claude-guard*"</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 网卡清单（决定 DNS 要设在哪些网卡上）</span></div></div><div><div><div>9</div></div><div><span>Get-NetAdapter</span><span> | </span><span>Select-Object</span><span> Name, InterfaceDescription</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># 代理形态（有无 TUN 网卡，决定 hosts 层取舍）</span></div></div><div><div><div>12</div></div><div><span>Get-Process</span><span> | </span><span>Where-Object</span><span><span> Name </span><span>-match</span><span> </span></span><span>"clash|mihomo|verge"</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span># WSL 与 Docker</span></div></div><div><div><div>15</div></div><div><span><span>wsl </span><span>-</span><span>l </span><span>-</span><span>v</span></span></div></div><div><div><div>16</div></div><div><span>docker ps</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>Anthropic 网段沿用服务器版 2026-10-21 值：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>IPv4: 160.79.104.0/21</span></div></div><div><div><div>2</div></div><div><span>IPv6: 2607:6bc0::/32</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section>
<section><h2>3. 第一步：Windows 防火墙出站阻断（A）<a href="#3-第一步windows-防火墙出站阻断a"><span>#</span></a></h2><section><h3>3.1 提权脚本 <code>setup.ps1</code>（必须纯 ASCII）<a href="#31-提权脚本-setupps1必须纯-ascii"><span>#</span></a></h3><p>创建 <code>C:\Users\&lt;你&gt;\AppData\Local\Temp\claude-guard\setup.ps1</code>：</p><div><div><div><figure><figcaption><span></span><span>Terminal window</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span># claude-guard setup for Windows 11 (run elevated) - ASCII only</span></div></div><div><div><div>2</div></div><div><span>$ErrorActionPreference</span><span><span> </span><span>=</span><span> </span></span><span>'Continue'</span></div></div><div><div><div>3</div></div><div><span>$dir</span><span><span> </span><span>=</span><span> </span></span><span>'C:\Users\&lt;你&gt;\AppData\Local\Temp\claude-guard'</span></div></div><div><div><div>4</div></div><div><span>$log</span><span><span> </span><span>=</span><span> </span></span><span>Join-Path</span><span> </span><span>$dir</span><span> </span><span>'setup.log'</span></div></div><div><div><div>5</div></div><div><span>function</span><span> </span><span>Log</span><span>([</span><span>string</span><span>]</span><span>$m</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>Add-Content</span><span><span> </span><span>-</span><span>Path </span></span><span>$log</span><span><span> </span><span>-</span><span>Value (</span></span><span>'[{0}] {1}'</span><span> </span><span>-f</span><span> (</span><span>Get-Date</span><span><span> </span><span>-</span><span>Format s), </span></span><span>$m</span><span><span>) </span><span>-</span><span>Encoding utf8</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>Log </span><span>'=== setup start ==='</span></div></div><div><div><div>9</div></div><div><span>$isAdmin</span><span><span> </span><span>=</span><span> ([</span></span><span>Security.Principal.WindowsPrincipal</span><span>][</span><span>Security.Principal.WindowsIdentity</span><span>]::GetCurrent()).IsInRole([</span><span>Security.Principal.WindowsBuiltInRole</span><span>]::Administrator)</span></div></div><div><div><div>10</div></div><div><span>Log (</span><span><span>"IsAdmin=</span><span>$</span></span><span>isAdmin</span><span>"</span><span>)</span></div></div><div><div><div>11</div></div><div><span>if</span><span><span> (</span><span>-not</span><span> </span></span><span>$isAdmin</span><span>) { Log </span><span>'ABORT: not elevated'</span><span>; </span><span>exit</span><span> </span><span>1</span><span> }</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># --- A: firewall block rules (kernel-level, persistent) ---</span></div></div><div><div><div>14</div></div><div><span>foreach</span><span> (</span><span>$n</span><span> </span><span>in</span><span> </span><span>@</span><span>(</span><span>'claude-guard-v4'</span><span>,</span><span>'claude-guard-v6'</span><span>,</span><span>'claude-guard-selftest-v4'</span><span>)) {</span></div></div><div><div><div>15</div></div><div><span>    </span><span>Get-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>$n</span><span><span> </span><span>-</span><span>ErrorAction SilentlyContinue | </span></span><span>Remove-NetFirewallRule</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div><div><div><div>17</div></div><div><span>New-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>'claude-guard-v4'</span><span><span> </span><span>-</span><span>Direction Outbound </span><span>-</span><span>Action Block </span><span>-</span><span>RemoteAddress </span></span><span>'160.79.104.0/21'</span><span><span> </span><span>-</span><span>Profile Any </span><span>-</span><span>Enabled True | </span></span><span>Out-Null</span></div></div><div><div><div>18</div></div><div><span>New-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>'claude-guard-v6'</span><span><span> </span><span>-</span><span>Direction Outbound </span><span>-</span><span>Action Block </span><span>-</span><span>RemoteAddress </span></span><span>'2607:6bc0::/32'</span><span><span> </span><span>-</span><span>Profile Any </span><span>-</span><span>Enabled True | </span></span><span>Out-Null</span></div></div><div><div><div>19</div></div><div><span>New-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>'claude-guard-selftest-v4'</span><span><span> </span><span>-</span><span>Direction Outbound </span><span>-</span><span>Action Block </span><span>-</span><span>RemoteAddress </span></span><span>'223.5.5.5/32'</span><span><span> </span><span>-</span><span>Profile Any </span><span>-</span><span>Enabled True | </span></span><span>Out-Null</span></div></div><div><div><div>20</div></div><div><span>Log </span><span>'firewall: claude-guard-v4 / claude-guard-v6 / claude-guard-selftest-v4 created'</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span># --- E1: DNS on non-virtual adapters (anti-hijack) ---</span></div></div><div><div><div>23</div></div><div><span>$adapters</span><span><span> </span><span>=</span><span> </span></span><span>Get-NetAdapter</span><span> | </span><span>Where-Object</span><span> { $_</span><span>.InterfaceDescription</span><span><span> </span><span>-notmatch</span><span> </span></span><span>'Hyper-V|Virtual|TAP-Windows|OpenVPN|WSL'</span><span> }</span></div></div><div><div><div>24</div></div><div><span>foreach</span><span> (</span><span>$a</span><span> </span><span>in</span><span> </span><span>$adapters</span><span>) {</span></div></div><div><div><div>25</div></div><div><span>    </span><span>Set-DnsClientServerAddress</span><span><span> </span><span>-</span><span>InterfaceAlias </span></span><span>$a.Name</span><span><span> </span><span>-</span><span>ServerAddresses </span></span><span>@</span><span>(</span><span>'223.5.5.5'</span><span>,</span><span>'119.29.29.29'</span><span>)</span></div></div><div><div><div>26</div></div><div><span>    </span><span>$now</span><span><span> </span><span>=</span><span> (</span></span><span>Get-DnsClientServerAddress</span><span><span> </span><span>-</span><span>InterfaceAlias </span></span><span>$a.Name</span><span><span> </span><span>-</span><span>AddressFamily </span></span><span>2</span><span>).ServerAddresses -join </span><span>','</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>Log (</span><span>'DNS set on ['</span><span><span> </span><span>+</span><span> </span></span><span>$a.Name</span><span><span> </span><span>+</span><span> </span></span><span>'] desc=['</span><span><span> </span><span>+</span><span> </span></span><span>$a.InterfaceDescription</span><span><span> </span><span>+</span><span> </span></span><span>'] now='</span><span><span> </span><span>+</span><span> </span></span><span>$now</span><span>)</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div><div><div><div>29</div></div><div><span><span>ipconfig </span><span>/</span><span>flushdns | </span></span><span>Out-Null</span></div></div><div><div><div>30</div></div><div><span>Log </span><span>'dns cache flushed'</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span># --- E2: hosts (aux name-layer, fail-closed) ---</span></div></div><div><div><div>33</div></div><div><span>$hostsPath</span><span><span> </span><span>=</span><span> </span></span><span>Join-Path</span><span> </span><span>$env:SystemRoot</span><span> </span><span>'System32\drivers\etc\hosts'</span></div></div><div><div><div>34</div></div><div><span>Copy-Item</span><span> </span><span>$hostsPath</span><span> (</span><span>$hostsPath</span><span><span> </span><span>+</span><span> </span></span><span>'.bak-claude-guard'</span><span><span>) </span><span>-</span><span>Force</span></span></div></div><div><div><div>35</div></div><div><span>$domains</span><span><span> </span><span>=</span><span> </span></span><span>@</span><span>(</span><span>'anthropic.com'</span><span>,</span><span>'www.anthropic.com'</span><span>,</span><span>'api.anthropic.com'</span><span>,</span><span>'console.anthropic.com'</span><span>,</span><span>'docs.anthropic.com'</span><span>,</span><span>'code.anthropic.com'</span><span>,</span><span>'statsig.anthropic.com'</span><span>,</span><span>'claude.ai'</span><span>,</span><span>'www.claude.ai'</span><span>,</span><span>'claude.com'</span><span>,</span><span>'www.claude.com'</span><span>,</span><span>'claudeusercontent.com'</span><span>)</span></div></div><div><div><div>36</div></div><div><span>$text</span><span><span> </span><span>=</span><span> [</span></span><span>System.IO.File</span><span>]::ReadAllText(</span><span>$hostsPath</span><span>)</span></div></div><div><div><div>37</div></div><div><span>$add</span><span><span> </span><span>=</span><span> </span></span><span>@</span><span>()</span></div></div><div><div><div>38</div></div><div><span>foreach</span><span> (</span><span>$d</span><span> </span><span>in</span><span> </span><span>$domains</span><span>) {</span></div></div><div><div><div>39</div></div><div><span>    </span><span>if</span><span> (</span><span>$text</span><span><span> </span><span>-notmatch</span><span> (</span></span><span>'(?m)^\s*0\.0\.0\.0\s+'</span><span><span> </span><span>+</span><span> [</span></span><span>regex</span><span>]::Escape(</span><span>$d</span><span><span>) </span><span>+</span><span> </span></span><span>'\s*$'</span><span>)) { </span><span>$add</span><span><span> </span><span>+=</span><span> (</span></span><span>'0.0.0.0 '</span><span><span> </span><span>+</span><span> </span></span><span>$d</span><span>) }</span></div></div><div><div><div>40</div></div><div><span>}</span></div></div><div><div><div>41</div></div><div><span>if</span><span> (</span><span>$add.Count</span><span><span> </span><span>-gt</span><span> </span></span><span>0</span><span>) {</span></div></div><div><div><div>42</div></div><div><span>    </span><span>$block</span><span><span> </span><span>=</span><span> </span></span><span>"</span><span>`r`n</span><span># claude-guard: aux name-layer block (fail-closed)</span><span>`r`n</span><span>"</span><span><span> </span><span>+</span><span> (</span></span><span>$add</span><span> -join </span><span>"</span><span>`r`n</span><span>"</span><span><span>) </span><span>+</span><span> </span></span><span>"</span><span>`r`n</span><span>"</span></div></div><div><div><div>43</div></div><div><span><span>    </span></span><span>[</span><span>System.IO.File</span><span>]::AppendAllText(</span><span>$hostsPath</span><span>, </span><span>$block</span><span>, [</span><span>System.Text.Encoding</span><span>]::ASCII)</span></div></div><div><div><div>44</div></div><div><span><span>    </span></span><span>Log (</span><span>'hosts: '</span><span><span> </span><span>+</span><span> </span></span><span>$add.Count</span><span><span> </span><span>+</span><span> </span></span><span>' lines added'</span><span>)</span></div></div><div><div><div>45</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>Log </span><span>'hosts: already up to date'</span></div></div><div><div><div>47</div></div><div><span>}</span></div></div><div><div><div>48</div></div><div>
</div></div><div><div><div>49</div></div><div><span># --- summary ---</span></div></div><div><div><div>50</div></div><div><span>Get-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>'claude-guard*'</span><span> | </span><span>ForEach-Object</span><span> {</span></div></div><div><div><div>51</div></div><div><span><span>    </span></span><span>Log (</span><span>'rule: '</span><span><span> </span><span>+</span><span> $_</span></span><span>.DisplayName</span><span><span> </span><span>+</span><span> </span></span><span>' enabled='</span><span><span> </span><span>+</span><span> $_</span></span><span>.Enabled</span><span><span> </span><span>+</span><span> </span></span><span>' action='</span><span><span> </span><span>+</span><span> $_</span></span><span>.Action</span><span><span> </span><span>+</span><span> </span></span><span>' dir='</span><span><span> </span><span>+</span><span> $_</span></span><span>.Direction</span><span>)</span></div></div><div><div><div>52</div></div><div><span>}</span></div></div><div><div><div>53</div></div><div><span>Log </span><span>'=== setup done ==='</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>注意：<code>$dir</code> 换成你自己的实际路径；脚本<strong>幂等</strong>，重复执行会先删旧规则再重建。</p><p>脚本一次做三件事：A 防火墙规则、E1 DNS、E2 hosts。其中 <code>claude-guard-selftest-v4</code>（封 223.5.5.5）是<strong>替身规则</strong>，专门给第 6 节验证用，验证完必须删。</p></section><section><h3>3.2 提权入口 <code>run-elevated.ps1</code>（必须纯 ASCII）<a href="#32-提权入口-run-elevatedps1必须纯-ascii"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># claude-guard elevated launcher (ASCII only)</span></div></div><div><div><div>2</div></div><div><span>$ErrorActionPreference</span><span><span> </span><span>=</span><span> </span></span><span>'Continue'</span></div></div><div><div><div>3</div></div><div><span>$base</span><span><span> </span><span>=</span><span> </span></span><span>'C:\Users\&lt;你&gt;\AppData\Local\Temp\claude-guard'</span></div></div><div><div><div>4</div></div><div><span>Start-Transcript</span><span><span> </span><span>-</span><span>Path (</span></span><span>Join-Path</span><span> </span><span>$base</span><span> </span><span>'elev.transcript.log'</span><span><span>) </span><span>-</span><span>Force | </span></span><span>Out-Null</span></div></div><div><div><div>5</div></div><div><span>try</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&amp; (</span><span>Join-Path</span><span> </span><span>$base</span><span> </span><span>'setup.ps1'</span><span>)</span></div></div><div><div><div>7</div></div><div><span>    </span><span>Add-Content</span><span><span> </span><span>-</span><span>Path (</span></span><span>Join-Path</span><span> </span><span>$base</span><span> </span><span>'elev.status.log'</span><span><span>) </span><span>-</span><span>Value </span></span><span>'WRAPPER_OK'</span></div></div><div><div><div>8</div></div><div><span>} </span><span>catch</span><span> {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>Add-Content</span><span><span> </span><span>-</span><span>Path (</span></span><span>Join-Path</span><span> </span><span>$base</span><span> </span><span>'elev.status.log'</span><span><span>) </span><span>-</span><span>Value (</span></span><span>'WRAPPER_ERR: '</span><span><span> </span><span>+</span><span> ($_ | </span></span><span>Out-String</span><span>))</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>Stop-Transcript</span><span> | </span><span>Out-Null</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>普通终端执行（会弹 UAC，点”是”）：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span><span>powershell </span><span>-</span><span>NoProfile </span><span>-</span><span>Command </span></span><span>'try { Start-Process powershell -Verb RunAs -Wait -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-File","C:\Users\&lt;你&gt;\AppData\Local\Temp\claude-guard\run-elevated.ps1" -ErrorAction Stop; Write-Output UAC_OK } catch { Write-Output ("UAC_FAIL: " + $_.Exception.Message) }'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>成功标志：<code>UAC_OK</code> + <code>setup.log</code> 里出现 <code>=== setup done ===</code>。</p></section><section><h3>3.3 提权失败排查（本次踩过的坑）<a href="#33-提权失败排查本次踩过的坑"><span>#</span></a></h3><p>症状：<code>UAC_OK</code> 打印了，但 <code>setup.log</code> 不存在、规则没生效、命令 1.5 秒就返回。</p><p>排查顺序：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 1. 非提权直接跑，把 ParserError 打到控制台（会因 IsAdmin=False 中止，无副作用）</span></div></div><div><div><div>2</div></div><div><span><span>powershell </span><span>-</span><span>NoProfile </span><span>-</span><span>ExecutionPolicy Bypass </span><span>-</span><span>File C:\Users\&lt;你&gt;\AppData\Local\Temp\claude</span><span>-</span><span>guard\setup.ps1</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 2. 看包装器日志</span></div></div><div><div><div>5</div></div><div><span><span>type C:\Users\&lt;你&gt;\AppData\Local\Temp\claude</span><span>-</span><span>guard\elev.status.log</span></span></div></div><div><div><div>6</div></div><div><span><span>type C:\Users\&lt;你&gt;\AppData\Local\Temp\claude</span><span>-</span><span>guard\elev.transcript.log</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>本次根因即第 1 节坑 1：UTF-8 无 BOM + 中文 → GBK 解析 → ParserError。改成纯 ASCII 后一次通过。</p><hr /></section></section>
<section><h2>4. 第二步：WSL2 内 nftables 移植（B）<a href="#4-第二步wsl2-内-nftables-移植b"><span>#</span></a></h2><p>与服务器版同款，去掉服务商中转 set（那是服务器服务商特有的）。WSL 内是 systemd 环境（Ubuntu-24.04 默认 <code>systemd=true</code>），直接复用 <code>claude-guard.service</code>。</p><section><h3>4.1 <code>/etc/nftables.d/claude-guard.nft</code><a href="#41-etcnftablesdclaude-guardnft"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>table inet claude_guard {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>set anthropic_v4 {</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>type ipv4_addr</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>flags interval</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>elements = { 160.79.104.0/21 }</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>set anthropic_v6 {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>type ipv6_addr</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>flags interval</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>elements = { 2607:6bc0::/32 }</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>chain output {</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>type filter hook output priority -200; policy accept;</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>ip daddr @anthropic_v4 counter limit rate 10/minute log prefix "claude-guard-out " level warn</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>ip daddr @anthropic_v4 counter drop</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>ip6 daddr @anthropic_v6 counter limit rate 10/minute log prefix "claude-guard-out6 " level warn</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>ip6 daddr @anthropic_v6 counter drop</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>chain forward {</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>type filter hook forward priority -200; policy accept;</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>ip daddr @anthropic_v4 counter limit rate 10/minute log prefix "claude-guard-fwd " level warn</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>ip daddr @anthropic_v4 counter drop</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>ip6 daddr @anthropic_v6 counter limit rate 10/minute log prefix "claude-guard-fwd6 " level warn</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>ip6 daddr @anthropic_v6 counter drop</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>4.2 <code>/usr/local/sbin/claude-guard.sh</code><a href="#42-usrlocalsbinclaude-guardsh"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/sh</span></div></div><div><div><div>2</div></div><div><span>set</span><span> </span><span>-eu</span></div></div><div><div><div>3</div></div><div><span>nft</span><span> </span><span>delete</span><span> </span><span>table</span><span> </span><span>inet</span><span> </span><span>claude_guard</span><span> 2&gt;</span><span>/dev/null</span><span> || </span><span>true</span></div></div><div><div><div>4</div></div><div><span>nft</span><span> </span><span>-f</span><span> </span><span>/etc/nftables.d/claude-guard.nft</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4.3 <code>/etc/systemd/system/claude-guard.service</code><a href="#43-etcsystemdsystemclaude-guardservice"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>[Unit]</span></div></div><div><div><div>2</div></div><div><span>Description</span><span><span>=</span><span>Block direct egress to Anthropic/Claude IP ranges</span></span></div></div><div><div><div>3</div></div><div><span>After</span><span><span>=</span><span>network.target</span></span></div></div><div><div><div>4</div></div><div><span>Wants</span><span><span>=</span><span>network.target</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>[Service]</span></div></div><div><div><div>7</div></div><div><span>Type</span><span><span>=</span><span>oneshot</span></span></div></div><div><div><div>8</div></div><div><span>RemainAfterExit</span><span><span>=</span><span>yes</span></span></div></div><div><div><div>9</div></div><div><span>ExecStart</span><span><span>=</span><span>/usr/local/sbin/claude-guard.sh</span></span></div></div><div><div><div>10</div></div><div><span>ExecStop</span><span><span>=</span><span>/usr/sbin/nft delete table inet claude_guard</span></span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>[Install]</span></div></div><div><div><div>13</div></div><div><span>WantedBy</span><span><span>=</span><span>multi-user.target</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4.4 部署（在 Windows 侧执行）<a href="#44-部署在-windows-侧执行"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 装 nftables（WSL 默认没有 nft 二进制）</span></div></div><div><div><div>2</div></div><div><span><span>wsl </span><span>-</span><span>d Ubuntu</span><span>-</span></span><span>24.04</span><span><span> </span><span>-</span><span>u root </span><span>--</span><span> bash </span><span>-</span><span>c </span></span><span>"apt-get update -qq &amp;&amp; apt-get install -y -qq nftables"</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 三个文件按上面内容写入后：</span></div></div><div><div><div>5</div></div><div><span><span>wsl </span><span>-</span><span>d Ubuntu</span><span>-</span></span><span>24.04</span><span><span> </span><span>-</span><span>u root </span><span>--</span><span> bash </span><span>-</span><span>c </span></span><span>"chmod 0755 /usr/local/sbin/claude-guard.sh; nft -c -f /etc/nftables.d/claude-guard.nft &amp;&amp; systemctl daemon-reload &amp;&amp; systemctl enable --now claude-guard.service"</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 验证</span></div></div><div><div><div>8</div></div><div><span><span>wsl </span><span>-</span><span>d Ubuntu</span><span>-</span></span><span>24.04</span><span><span> </span><span>-</span><span>u root </span><span>--</span><span> bash </span><span>-</span><span>c </span></span><span>"systemctl is-enabled claude-guard; systemctl is-active claude-guard; nft list table inet claude_guard"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>期望：<code>enabled</code> / <code>active</code>，规则集列出两个 set 和两条链。WSL 每次启动由 systemd 自动拉起，等效开机持久。</p><hr /></section></section>
<section><h2>5. 第三步：DNS 纠正 + hosts（E）<a href="#5-第三步dns-纠正--hostse"><span>#</span></a></h2><p>这两步已包含在 <code>setup.ps1</code>（3.1 的 E1/E2 段），要点：</p><ul>
<li><strong>DNS 选 223.5.5.5 / 119.29.29.29</strong>（阿里 DNSPod）：大陆家宽可达且不劫持 Anthropic 域名；服务器版的 1.1.1.1/8.8.8.8 在大陆不可靠，不要照抄。排除虚拟网卡（Hyper-V/WSL/OpenVPN/TAP），只设物理网卡。</li>
<li><strong>hosts 指向 0.0.0.0</strong>：辅助名称层，共 12 条（anthropic.com / claude.ai / claude.com / claudeusercontent.com 及主要子域）。走 HTTP 代理时域名由代理端解析，hosts 不影响代理路径。</li>
<li>两层都是辅助：DoH 应用会绕过它们，所以<strong>IP 层封锁（A/B）才是最终保证</strong>。</li>
</ul><hr /></section>
<section><h2>6. 验证：替身法（全程零 Anthropic 流量）<a href="#6-验证替身法全程零-anthropic-流量"><span>#</span></a></h2><p>原理：<code>setup.ps1</code> 额外创建了替身规则 <code>claude-guard-selftest-v4</code>（封 223.5.5.5/32）。它与正式规则<strong>构造完全一致</strong>，对它做行为测试即可证明正式规则的机制。</p><section><h3>6.1 主机差异测试<a href="#61-主机差异测试"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 被替身规则封住的解析器：必须超时</span></div></div><div><div><div>2</div></div><div><span><span>nslookup </span><span>-</span><span>timeout</span><span>=</span></span><span>2</span><span><span> </span><span>-</span><span>retry</span><span>=</span></span><span>1</span><span> </span><span>baidu.com</span><span> </span><span>223.5</span><span>.</span><span>5.5</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 对照组（未封的解析器）：必须正常</span></div></div><div><div><div>5</div></div><div><span><span>nslookup </span><span>-</span><span>timeout</span><span>=</span></span><span>2</span><span><span> </span><span>-</span><span>retry</span><span>=</span></span><span>1</span><span> </span><span>baidu.com</span><span> </span><span>119.29</span><span>.</span><span>29.29</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>期望：前者 <code>DNS request timed out</code>，后者返回 A 记录。</p></section><section><h3>6.2 Docker Desktop 覆盖判定<a href="#62-docker-desktop-覆盖判定"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span><span>docker run </span><span>--</span><span>rm node:</span></span><span>22</span><span><span>-</span><span>alpine sh </span><span>-</span><span>c </span></span><span>"nslookup -timeout=2 baidu.com 223.5.5.5"</span></div></div><div><div><div>2</div></div><div><span><span>docker run </span><span>--</span><span>rm node:</span></span><span>22</span><span><span>-</span><span>alpine sh </span><span>-</span><span>c </span></span><span>"nslookup -timeout=2 baidu.com 119.29.29.29"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>期望：前者 <code>connection timed out; no servers could be reached</code>，后者正常。
若前者正常，说明你的 Docker 网络路径没被 A 覆盖，需要把工作负载挪进 WSL（B 覆盖）再验。</p></section><section><h3>6.3 本次实测记录（2026-10-22）<a href="#63-本次实测记录2026-10-22"><span>#</span></a></h3>

<table><thead><tr><th>测试</th><th>结果</th></tr></thead><tbody><tr><td>主机 <code>nslookup baidu.com 223.5.5.5</code></td><td>超时（被拦）✓</td></tr><tr><td>主机 <code>nslookup baidu.com 119.29.29.29</code></td><td>正常返回 ✓</td></tr><tr><td>容器 <code>nslookup baidu.com 223.5.5.5</code></td><td>无服务器可达（被拦）✓ → <strong>Docker Desktop 被 A 覆盖</strong></td></tr><tr><td>容器 <code>nslookup baidu.com 119.29.29.29</code></td><td>正常返回 ✓</td></tr><tr><td>主机冒烟 <code>curl https://www.baidu.com</code></td><td>200，无误伤 ✓</td></tr><tr><td>WSL <code>getent hosts baidu.com</code></td><td>正常 ✓</td></tr></tbody></table></section><section><h3>6.4 清理替身规则（必须做）<a href="#64-清理替身规则必须做"><span>#</span></a></h3><p>替身规则封的 223.5.5.5 现在是主 DNS，验证完立即删（会再弹一次 UAC）：</p><p><code>teardown-selftest.ps1</code>：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$log</span><span><span> </span><span>=</span><span> </span></span><span>'C:\Users\&lt;你&gt;\AppData\Local\Temp\claude-guard\setup.log'</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>Log</span><span>([</span><span>string</span><span>]</span><span>$m</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Add-Content</span><span><span> </span><span>-</span><span>Path </span></span><span>$log</span><span><span> </span><span>-</span><span>Value (</span></span><span>'[{0}] {1}'</span><span> </span><span>-f</span><span> (</span><span>Get-Date</span><span><span> </span><span>-</span><span>Format s), </span></span><span>$m</span><span><span>) </span><span>-</span><span>Encoding utf8</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>Get-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>'claude-guard-selftest-v4'</span><span><span> </span><span>-</span><span>ErrorAction SilentlyContinue | </span></span><span>Remove-NetFirewallRule</span></div></div><div><div><div>6</div></div><div><span>Log </span><span>'selftest rule removed'</span></div></div><div><div><div>7</div></div><div><span>Get-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>'claude-guard*'</span><span> | </span><span>ForEach-Object</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>Log (</span><span>'remaining: '</span><span><span> </span><span>+</span><span> $_</span></span><span>.DisplayName</span><span><span> </span><span>+</span><span> </span></span><span>' enabled='</span><span><span> </span><span>+</span><span> $_</span></span><span>.Enabled</span><span>)</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>Log </span><span>'=== teardown done ==='</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span><span>powershell </span><span>-</span><span>NoProfile </span><span>-</span><span>Command </span></span><span>'try { Start-Process powershell -Verb RunAs -Wait -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-File","C:\Users\&lt;你&gt;\AppData\Local\Temp\claude-guard\teardown-selftest.ps1" -ErrorAction Stop; Write-Output UAC_OK } catch { Write-Output ("UAC_FAIL: " + $_.Exception.Message) }'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>最终盘点（期望只剩两条正式规则）：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>Get-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>"claude-guard*"</span><span> | </span><span>Format-Table</span><span> DisplayName,Enabled,Action,Direction,Profile</span></div></div><div><div><div>2</div></div><div><span>Get-DnsClientServerAddress</span><span><span> </span><span>-</span><span>AddressFamily </span></span><span>2</span><span> | </span><span>Format-Table</span><span> InterfaceAlias,ServerAddresses</span></div></div><div><div><div>3</div></div><div><span>type C:\Windows\System32\drivers\etc\hosts</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2>7. 端到端不连通实测（2026-10-22 已执行通过）<a href="#7-端到端不连通实测2026-10-22-已执行通过"><span>#</span></a></h2><p>上面的验证证明了”机制有效 + 无误伤”，但没有产生任何 Anthropic 流量。端到端确认方法如下（本次已执行，实测记录见 7.1）：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 1. 先验证代理路径（期望 401：网络可达，只是缺凭证）</span></div></div><div><div><div>2</div></div><div><span>curl.exe</span><span><span> </span><span>-</span><span>x http:</span><span>//</span></span><span>127.0</span><span>.</span><span>0.1</span><span>:</span><span>7890</span><span><span> </span><span>-</span><span>m </span></span><span>15</span><span><span> </span><span>-</span><span>o NUL </span><span>-</span><span>w </span></span><span>"proxy_http=%{http_code}\n"</span><span><span> https:</span><span>//</span></span><span>api.anthropic.com</span><span><span>/</span><span>v1</span><span>/</span><span>models</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 2. 再验证直连路径（期望超时 / http=000）</span></div></div><div><div><div>5</div></div><div><span>curl.exe</span><span><span> </span><span>--</span><span>noproxy </span></span><span>"*"</span><span><span> </span><span>-</span><span>m </span></span><span>6</span><span><span> </span><span>-</span><span>o NUL </span><span>-</span><span>w </span></span><span>"direct_http=%{http_code}\n"</span><span><span> https:</span><span>//</span></span><span>api.anthropic.com</span><span><span>/</span><span>v1</span><span>/</span><span>models</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>务必先 1 后 2。若第 2 步返回任何非 000 状态，<strong>立即停止使用并回报</strong>，说明封锁有洞。</p><section><h3>7.1 本次实测记录（2026-10-22）<a href="#71-本次实测记录2026-10-22"><span>#</span></a></h3><p>实际执行的是”不连通”电池：对照组 + 三层直击，用 <code>--resolve</code> 强制打真实 Anthropic IP（绕过 DNS/hosts，直击内核封锁层）：</p>

<table><thead><tr><th>测试</th><th>命令要点</th><th>结果</th><th>证据含义</th></tr></thead><tbody><tr><td>对照组</td><td><code>curl https://www.baidu.com</code></td><td><code>200</code></td><td>工具链正常，后续失败不是假象</td></tr><tr><td>hosts 层</td><td><code>curl --noproxy "*" https://api.anthropic.com/v1/models</code></td><td><code>(6) Could not resolve host</code>，<code>000</code></td><td>名称层拒绝解析，零流量</td></tr><tr><td>内核层 IPv4</td><td><code>--resolve api.anthropic.com:443:160.79.104.10</code></td><td><code>(7) Failed after 0 ms</code>，<code>000</code></td><td>0 ms 瞬时失败 = WFP 在 ALE connect 层本机拒绝，SYN 未出网卡</td></tr><tr><td>内核层 IPv6</td><td><code>--resolve api.anthropic.com:443:[2607:6bc0::10]</code></td><td><code>(7) Failed after 0 ms</code>，<code>000</code></td><td>v6 同样内核层拒绝</td></tr><tr><td>WSL 内核层</td><td>WSL 内同款 <code>--resolve</code> + <code>nft list</code> 计数器</td><td><code>(28) 超时</code>，<code>000</code>；计数器 <code>packets 6 bytes 360</code></td><td>nftables 静默丢弃，计数器实锤</td></tr></tbody></table><p>判定：<strong>“直连必死”端到端成立</strong>。主机签名 = 瞬时拒绝（无包发出）；WSL 签名 = 丢弃 + 计数器递增。
代理路径未在本次测试（不发凭证请求）；“走代理可用”由机制保证——封锁只按目的 IP 生效，代理节点 IP 不在封锁集合内，HTTP 代理下域名由代理端解析、hosts 不参与。</p><hr /></section></section>
<section><h2>8. 维护<a href="#8-维护"><span>#</span></a></h2><section><h3>8.1 Anthropic IP 段变化<a href="#81-anthropic-ip-段变化"><span>#</span></a></h3><p>当前（2026-10-21）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>160.79.104.0/21</span></div></div><div><div><div>2</div></div><div><span>2607:6bc0::/32</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>变更时改两处并重载：</p><ol>
<li><code>setup.ps1</code> 里两条 <code>New-NetFirewallRule</code> 的 <code>RemoteAddress</code> → 重跑 <code>run-elevated.ps1</code>（幂等，会重建规则）；</li>
<li>WSL <code>/etc/nftables.d/claude-guard.nft</code> 的 <code>elements</code> → <code>wsl -d Ubuntu-24.04 -u root -- /usr/local/sbin/claude-guard.sh</code>。</li>
</ol></section><section><h3>8.2 换机器 / 重装<a href="#82-换机器--重装"><span>#</span></a></h3><p>复制 <code>claude-guard\</code> 目录（含本教程的脚本）→ 改 <code>$dir</code> 路径 → 跑 <code>run-elevated.ps1</code> → 第 4 节部署 WSL → 第 6 节替身验证。</p></section><section><h3>8.3 已知观察<a href="#83-已知观察"><span>#</span></a></h3><ul>
<li><code>nslookup</code> 显示实际应答服务器可能是 <code>fe80::1</code>（路由器 RA 下发的 IPv6 DNS），IPv4 DNS 已固定 223.5.5.5/119.29.29.29。Anthropic 域名链路被 hosts + IP 层闭合，不受影响；仅影响其他域名的 DNS 洁净度。</li>
<li>本机存在 OpenVPN 虚拟网卡，未动其 DNS（由 VPN 配置自理）。</li>
<li>Clash Verge（verge-mihomo）为显式代理模式；若将来开 TUN 模式见第 1 节坑 5。</li>
</ul><hr /></section></section>
<section><h2>9. 回滚<a href="#9-回滚"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 1. 删防火墙规则（管理员）</span></div></div><div><div><div>2</div></div><div><span>Remove-NetFirewallRule</span><span><span> </span><span>-</span><span>DisplayName </span></span><span>"claude-guard*"</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 2. 还原 DNS（管理员）</span></div></div><div><div><div>5</div></div><div><span>Set-DnsClientServerAddress</span><span><span> </span><span>-</span><span>InterfaceAlias WLAN </span><span>-</span><span>ResetServerAddresses</span></span></div></div><div><div><div>6</div></div><div><span>Set-DnsClientServerAddress</span><span><span> </span><span>-</span><span>InterfaceAlias </span></span><span>"以太网"</span><span><span> </span><span>-</span><span>ResetServerAddresses</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 3. 还原 hosts（管理员）</span></div></div><div><div><div>9</div></div><div><span><span>copy C:\Windows\System32\drivers\etc\hosts.bak</span><span>-</span><span>claude</span><span>-</span><span>guard C:\Windows\System32\drivers\etc\hosts</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 4. WSL 内</span></div></div><div><div><div>2</div></div><div><span><span>wsl </span><span>-</span><span>d Ubuntu</span><span>-</span></span><span>24.04</span><span><span> </span><span>-</span><span>u root </span><span>--</span><span> bash </span><span>-</span><span>c </span></span><span>"systemctl disable --now claude-guard; nft delete table inet claude_guard 2&gt;/dev/null; true"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>回滚后直连恢复，这是预期行为。</p><hr /></section>
<section><h2>10. 文件清单<a href="#10-文件清单"><span>#</span></a></h2>

<table><thead><tr><th>路径</th><th>作用</th></tr></thead><tbody><tr><td><code>C:\Users\&lt;你&gt;\AppData\Local\Temp\claude-guard\setup.ps1</code></td><td>主脚本：防火墙 + DNS + hosts（纯 ASCII，幂等）</td></tr><tr><td>同目录 <code>run-elevated.ps1</code></td><td>提权入口（UAC + transcript）</td></tr><tr><td>同目录 <code>teardown-selftest.ps1</code></td><td>删除替身规则</td></tr><tr><td>同目录 <code>setup.log</code></td><td>全部操作审计日志</td></tr><tr><td>同目录 <code>elev.status.log</code> / <code>elev.transcript.log</code></td><td>提权执行诊断</td></tr><tr><td><code>C:\Windows\System32\drivers\etc\hosts.bak-claude-guard</code></td><td>hosts 备份</td></tr><tr><td>WSL <code>/etc/nftables.d/claude-guard.nft</code></td><td>WSL 内核级封锁规则</td></tr><tr><td>WSL <code>/usr/local/sbin/claude-guard.sh</code></td><td>重载脚本</td></tr><tr><td>WSL <code>/etc/systemd/system/claude-guard.service</code></td><td>WSL 开机自启</td></tr></tbody></table><blockquote><p><code>Temp</code> 目录会被系统清理，长期留底请复制到 <code>&lt;笔记目录&gt;</code>。</p></blockquote><hr /></section>
<section><h2>11. 一句话总结<a href="#11-一句话总结"><span>#</span></a></h2><p><strong>Windows 防火墙封 IP 段（主机+Docker 实测全覆盖）+ WSL 内 nftables 双保险 + 公网 DNS/hosts 辅助层</strong>，并且用”替身 IP 差异测试”在零 Anthropic 流量的前提下证明机制有效——代理可用、直连必死、代理崩溃不回落。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/react-day1-basics/</id>
      <title type="text">React 学习 Day1：基础语法与整体框架（含 JS 关键基础）</title>
      <published>2026-10-08T00:00:00.000Z</published>
      <updated>2026-10-08T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/react-day1-basics/"/>
      <summary type="text">建立对 React 的整体认识，并补齐编写 React 所必需的 JavaScript 语法基础：组件化、Props/State、JSX 与常用概念。</summary>
      <content type="html"><![CDATA[<p>这一天的核心目标：建立对 React 的整体认识，并补齐编写 React 所必需的 JavaScript 语法基础。下面按知识模块做系统化回顾，并在原笔记基础上补充更多细节、例子与易错点。</p>
<hr />
<section><h2>1. React 是什么（宏观理解）<a href="#1-react-是什么宏观理解"><span>#</span></a></h2><ul>
<li>React 是一个<strong>用于构建用户界面（UI）<strong>的 JavaScript 库，重点负责</strong>视图层（View Layer）</strong>。</li>
<li>React 的编程范式是<strong>声明式（Declarative）</strong>：你只描述“界面应该长什么样”，React 负责“怎么更新到页面上”。</li>
<li>React 生态下通常构建<strong>单页应用（SPA）</strong>：页面不整页刷新，通过路由切换视图。</li>
</ul><p>对 Python 思维的类比：</p><ul>
<li>React 组件 ≈ Python 的函数/类，用来封装一段可复用的 UI 与逻辑。</li>
<li>Props ≈ 函数参数（外部输入）。</li>
<li>State ≈ 函数内部的可变局部状态/类的实例属性（内部数据）。</li>
</ul><hr /></section>
<section><h2>2. React 核心思想：组件化（Component-Based）<a href="#2-react-核心思想组件化component-based"><span>#</span></a></h2><section><h3>2.1 什么是组件<a href="#21-什么是组件"><span>#</span></a></h3><ul>
<li>React 应用由<strong>组件树</strong>组成：小组件组合成大组件，最终拼成页面。</li>
<li>组件负责<strong>一小块 UI + 相关逻辑</strong>，具有高复用性与可维护性。</li>
</ul><p>函数组件（现代主流）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>Hello</span><span><span>({ </span><span>name</span><span> }) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> &lt;</span><span>h1</span><span>&gt;Hello </span><span>{</span><span>name</span><span>}</span><span>&lt;/</span><span>h1</span><span>&gt;;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>组件组合（Composition）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>App</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> (</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>      </span></span><span>&lt;</span><span>Hello</span><span> </span><span>name</span><span>=</span><span>"Tom"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>&lt;</span><span>Hello</span><span> </span><span>name</span><span>=</span><span>"Jerry"</span><span> /&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2.2 函数组件 vs 类组件（只要知道差异）<a href="#22-函数组件-vs-类组件只要知道差异"><span>#</span></a></h3><ul>
<li><strong>函数组件</strong>：更简洁，配合 Hooks 写法统一，是现在 React 的标准。</li>
<li><strong>类组件</strong>：历史遗留写法，需要 <code>this</code>，生命周期冗长，新项目基本不再推荐。</li>
</ul><p>你现在只需要专注函数组件 + Hooks。</p><hr /></section></section>
<section><h2>3. React 的三大核心机制<a href="#3-react-的三大核心机制"><span>#</span></a></h2><section><h3>3.1 虚拟 DOM（Virtual DOM）与 Diff<a href="#31-虚拟-domvirtual-dom与-diff"><span>#</span></a></h3><p>为什么需要 Virtual DOM：</p><ul>
<li>真实 DOM 操作成本高。</li>
<li>React 先在内存里构建<strong>虚拟 DOM（JS 对象树）</strong>，再与旧树比较（diff），只把<strong>最小改动</strong>同步到真实 DOM。</li>
</ul><p>更新流程：</p><ol>
<li>State/Props 变化</li>
<li>组件重新执行 → 生成新的 Virtual DOM</li>
<li>React diff 旧树和新树</li>
<li>只更新需要变化的真实 DOM</li>
</ol><p>与列表渲染强相关的点：</p><ul>
<li><code>map</code> 渲染列表时要加 <code>key</code>，否则 diff 难以稳定复用节点。</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>items</span><span>.</span></span><span>map</span><span><span>(</span><span>item</span><span> </span></span><span>=&gt;</span><span> &lt;</span><span>li</span><span> </span><span>key</span><span><span>=</span><span>{</span><span>item</span><span>.</span></span><span>id</span><span><span>}</span><span>&gt;</span><span>{</span><span>item</span><span>.</span></span><span>title</span><span><span>}</span><span>&lt;/</span></span><span>li</span><span>&gt;)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>key</code> 要<strong>稳定且唯一</strong>，尽量不用 index 作为 key（数据会增删/重排时会出 bug）。</p></section><section><h3>3.2 Props 与 State<a href="#32-props-与-state"><span>#</span></a></h3><p><strong>Props（外部传入）</strong></p><ul>
<li>父组件 → 子组件的只读数据。</li>
<li>子组件不能直接修改 props，只能通过回调通知父组件。</li>
</ul><p><strong>State（组件内部）</strong></p><ul>
<li>组件自己维护的可变数据，变化会触发重渲染。</li>
<li>使用 <code>useState</code> 等 Hook 管理。</li>
</ul><p>单向数据流（React 的基本原则）：</p><ul>
<li>数据自顶向下传递（parent → child）。</li>
<li>子组件想影响父组件：通过 props 传函数（回调），由父组件更新自己的 state。</li>
</ul><p>状态提升（Lifting State Up）：</p><ul>
<li>当多个组件需要共享同一份数据，把 state 放到它们最近的共同父组件中。</li>
</ul></section><section><h3>3.3 Hooks（函数组件的“外挂能力”）<a href="#33-hooks函数组件的外挂能力"><span>#</span></a></h3><p>常用三件套：</p><ul>
<li><code>useState</code>：组件状态</li>
<li><code>useEffect</code>：副作用（请求/订阅/手动 DOM 操作）</li>
<li><code>useContext</code>：跨组件共享数据</li>
</ul><p>Hooks 两条硬规则：</p><ol>
<li>只能在函数组件或自定义 Hook 顶层调用（不能写在 if/for/函数里）。</li>
<li>不能在普通 JS 函数里调用。</li>
</ol><hr /></section></section>
<section><h2>4. React 项目启动与目录结构（以 Vite 为例）<a href="#4-react-项目启动与目录结构以-vite-为例"><span>#</span></a></h2><p>初始化项目：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>npm</span><span> </span><span>create</span><span> </span><span>vite@latest</span><span> </span><span>my-app</span><span> </span><span>--template</span><span> </span><span>react</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>典型结构：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>src/</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>main.jsx   # 入口：把 React 挂到 DOM</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>App.jsx    # 根组件：组织页面结构</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>assets/    # 静态资源</span></div></div><div><div><div>5</div></div><div><span>index.html   # 页面模板，提供 root 节点</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>main.jsx</code> 的作用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>ReactDOM</span><span> </span><span>from</span><span> </span><span>"react-dom/client"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>App</span><span> </span><span>from</span><span> </span><span>"./App.jsx"</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>ReactDOM</span><span>.</span></span><span>createRoot</span><span><span>(</span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"root"</span><span>)).</span><span>render</span><span>(&lt;</span><span>App</span><span> /&gt;);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>createRoot(...).render(...)</code> 相当于“启动 React 应用”。</li>
<li>React 会从 <code>App</code> 作为根节点往下渲染整棵组件树。</li>
</ul><hr /></section>
<section><h2>5. React 常见生态模块（知道用途即可）<a href="#5-react-常见生态模块知道用途即可"><span>#</span></a></h2><section><h3>5.1 路由（React Router）<a href="#51-路由react-router"><span>#</span></a></h3><p>用于 SPA 的页面切换：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>BrowserRouter</span><span>, </span><span>Routes</span><span>, </span><span>Route</span><span> } </span><span>from</span><span> </span><span>"react-router-dom"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>核心概念：</p><ul>
<li><code>BrowserRouter</code>：路由容器</li>
<li><code>Routes/Route</code>：路由表</li>
<li><code>Link</code>：无刷新跳转</li>
</ul></section><section><h3>5.2 全局状态管理（Redux / Zustand）<a href="#52-全局状态管理redux--zustand"><span>#</span></a></h3><p>什么时候需要全局状态：</p><ul>
<li>多个无关组件都要用/改同一份数据（例如用户信息、主题、购物车）。</li>
</ul><p>对比：</p><ul>
<li>Redux：强规范、生态大，但模板代码多。</li>
<li>Zustand：轻量直观，新手上手更快。</li>
</ul></section><section><h3>5.3 UI 组件库 / 样式方案<a href="#53-ui-组件库--样式方案"><span>#</span></a></h3><ul>
<li>Ant Design / Material UI / Chakra UI：现成高质量组件，提高开发效率。</li>
<li>Tailwind CSS：原子化/工具类 CSS，快速拼 UI。</li>
</ul><hr /></section></section>
<section><h2>6. React 应用的运行与更新流程<a href="#6-react-应用的运行与更新流程"><span>#</span></a></h2><p>整体心智模型：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>用户交互 → 触发事件 → setState 更新状态 → 组件重渲染 → Virtual DOM diff → 更新真实 DOM → UI 刷新</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>你在写什么：</p><ul>
<li>组件（UI 结构）</li>
<li>状态（数据）</li>
<li>事件（交互）</li>
<li>渲染（JSX 表达 UI）</li>
</ul><p>React 自动帮你做什么：</p><ul>
<li>数据变化驱动 UI 更新</li>
<li>DOM 最小化更新与性能优化</li>
</ul><hr /></section>
<section><h2>7. JavaScript 基础（React 必备子集）<a href="#7-javascript-基础react-必备子集"><span>#</span></a></h2><section><h3>7.1 let / const / var<a href="#71-let--const--var"><span>#</span></a></h3><ul>
<li><code>const</code>：默认使用，引用不可重新指向。</li>
<li><code>let</code>：需要重新赋值时用。</li>
<li><code>var</code>：不要用（函数作用域、变量提升问题）。</li>
</ul></section><section><h3>7.2 常用数据类型<a href="#72-常用数据类型"><span>#</span></a></h3><ul>
<li>字符串、数字、布尔值</li>
<li>数组：<code>[1, 2, 3]</code></li>
<li>对象：<code>{ name: "Tom", age: 20 }</code></li>
</ul><p>重点：数组/对象是<strong>引用类型</strong>，更新时要注意“不可变性”。</p></section><section><h3>7.3 函数与箭头函数<a href="#73-函数与箭头函数"><span>#</span></a></h3><p>React 中大量使用箭头函数：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) </span></span><span>=&gt;</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>特点：</p><ul>
<li>写法短</li>
<li><code>this</code> 绑定更直观（函数内 <code>this</code> 取外层）</li>
</ul></section><section><h3>7.4 条件与 JSX 条件渲染<a href="#74-条件与-jsx-条件渲染"><span>#</span></a></h3><p>JS：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span><span> (</span><span>x</span><span> </span></span><span>&gt;</span><span> </span><span>0</span><span><span>) </span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>"ok"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>JSX 常用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>{</span><span>isLogin</span><span> </span></span><span>?</span><span> &lt;</span><span>User</span><span> /&gt; </span><span>:</span><span> &lt;</span><span>Login</span><span> /&gt;}</span></div></div><div><div><div>2</div></div><div><span><span>{</span><span>list</span><span>.</span></span><span>length</span><span> </span><span>&gt;</span><span> </span><span>0</span><span> </span><span>&amp;&amp;</span><span> &lt;</span><span>List</span><span> /&gt;}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>7.5 map（列表渲染核心）<a href="#75-map列表渲染核心"><span>#</span></a></h3><p><code>map</code>：把数组映射成新数组，不改变原数组。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>nums</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>squares</span><span> </span><span>=</span><span><span> </span><span>nums</span><span>.</span></span><span>map</span><span><span>(</span><span>n</span><span> </span></span><span>=&gt;</span><span><span> </span><span>n</span><span> </span></span><span>*</span><span><span> </span><span>n</span><span>); </span></span><span>// [1,4,9]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>React 列表渲染：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>ul</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>  </span><span>{</span><span><span>names</span><span>.</span></span><span>map</span><span><span>(</span><span>name</span><span> </span></span><span>=&gt;</span><span> (</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span> </span><span>key</span><span><span>=</span><span>{</span><span>name</span><span>}</span><span>&gt;</span><span>{</span><span>name</span><span>}</span><span>&lt;/</span></span><span>li</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>))</span><span>}</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>7.6 解构（Destructuring）<a href="#76-解构destructuring"><span>#</span></a></h3><p>对象解构：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> { </span><span>name</span><span>:</span><span> </span><span>"Tom"</span><span>, </span><span>age</span><span>:</span><span> </span><span>20</span><span> };</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>name</span><span>, </span><span>age</span><span> } </span><span>=</span><span><span> </span><span>user</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>数组解构：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>nums</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>] </span><span>=</span><span><span> </span><span>nums</span><span>; </span></span><span>// a=1, b=2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>React 里 <code>useState</code> 就是数组解构：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>count</span><span>, </span><span>setCount</span><span>] </span><span>=</span><span> </span><span>useState</span><span>(</span><span>0</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>7.7 展开运算符（…）与不可变更新<a href="#77-展开运算符与不可变更新"><span>#</span></a></h3><p>数组更新：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr2</span><span> </span><span>=</span><span> [</span><span>...</span><span><span>arr1</span><span>, </span><span>newItem</span><span>];</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对象更新：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>newUser</span><span> </span><span>=</span><span> { </span><span>...</span><span><span>user</span><span>, </span></span><span>age</span><span>:</span><span> </span><span>21</span><span> };</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原因：React 依赖“引用变化”判断更新，因此要<strong>返回新对象/新数组</strong>。</p></section><section><h3>7.8 模块化 import / export<a href="#78-模块化-import--export"><span>#</span></a></h3><p>命名导出（named export）：</p><div><figure><figcaption><span>utils.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) { </span></span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>; }</span></span></div></div><div><div><div>2</div></div><div><span>// 使用</span></div></div><div><div><div>3</div></div><div><span>import</span><span> { </span><span>add</span><span> } </span><span>from</span><span> </span><span>"./utils"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>默认导出（default export）：</p><div><figure><figcaption><span>App.jsx</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>function</span><span> </span><span>App</span><span>() {}</span></div></div><div><div><div>2</div></div><div><span>// 使用</span></div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>App</span><span> </span><span>from</span><span> </span><span>"./App"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>export</code> 的使用场景：</p><ul>
<li>让<strong>其他文件/组件</strong>能复用你写的函数、组件、常量、Hook 等。</li>
</ul></section><section><h3>7.9 Promise 与 async/await<a href="#79-promise-与-asyncawait"><span>#</span></a></h3><p>Promise 写法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>fetch</span><span><span>(</span><span>url</span><span>).</span></span><span>then</span><span><span>(</span><span>r</span><span> </span></span><span>=&gt;</span><span><span> </span><span>r</span><span>.</span></span><span>json</span><span>()).</span><span>then</span><span><span>(</span><span>data</span><span> </span></span><span>=&gt;</span><span> </span><span>setList</span><span><span>(</span><span>data</span><span>));</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>async/await 写法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>getData</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>r</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>fetch</span><span><span>(</span><span>url</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>await</span><span><span> </span><span>r</span><span>.</span></span><span>json</span><span>();</span></div></div><div><div><div>4</div></div><div><span>  </span><span>setList</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>React 中常在 <code>useEffect</code> 里请求数据，并用 <code>try/catch</code> 做错误处理。</p><hr /></section></section>
<section><h2>8. day1 的重点 Q&amp;A 再巩固<a href="#8-day1-的重点-qa-再巩固"><span>#</span></a></h2><section><h3>8.1 Counter 例子为什么这样写<a href="#81-counter-例子为什么这样写"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>count</span><span>, </span><span>setCount</span><span>] </span><span>=</span><span> </span><span>useState</span><span>(</span><span>0</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>useState</code> 返回 <code>[当前值, 更新函数]</code>，用数组解构取出：</p><ul>
<li><code>count</code>：当前值</li>
<li><code>setCount</code>：更新值并触发重渲染</li>
</ul><p>点击按钮执行：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>onClick</span><span>=</span><span>{() =&gt; </span><span>setCount</span><span><span>(</span><span>count</span><span> + 1)}</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>→ 更新 state → React 自动重渲染 → UI 变动。</p></section><section><h3>8.2 map 的本质<a href="#82-map-的本质"><span>#</span></a></h3><ul>
<li>对每个元素执行回调函数</li>
<li>返回新数组</li>
<li>在 React 中用于“数组 → 组件列表”的转换</li>
</ul></section><section><h3>8.3 数组解构例子<a href="#83-数组解构例子"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>nums</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>] </span><span>=</span><span><span> </span><span>nums</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span><span> </span><span>nums</span><span>[</span></span><span>0</span><span>]; </span><span>// 1</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span><span> </span><span>nums</span><span>[</span></span><span>1</span><span>]; </span><span>// 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>8.4 export 给谁用<a href="#84-export-给谁用"><span>#</span></a></h3><p>你写的内容需要<strong>跨文件复用</strong>时导出：</p><ul>
<li>组件</li>
<li>工具函数</li>
<li>常量/配置</li>
<li>API 封装</li>
<li>自定义 Hook</li>
</ul><hr /></section></section>
<section><h2>9. 学习路径（下一步怎么走）<a href="#9-学习路径下一步怎么走"><span>#</span></a></h2><ol>
<li>把 JS 必备子集练熟：<code>const/let</code>、箭头函数、解构、展开、<code>map</code>、模块化、异步。</li>
<li>深入 React 核心：组件写法、props/state、<code>useState/useEffect</code>、列表/条件渲染。</li>
<li>做小项目巩固：Todo List / 个人博客前端 / 管理后台等。</li>
</ol><p>只要把今天这些“最小必备知识”真正用起来，你就能开始写 React 项目了。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/poetry-cheatsheet/</id>
      <title type="text">Poetry 命令大全及更新指南</title>
      <published>2026-10-02T00:00:00.000Z</published>
      <updated>2026-10-02T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/poetry-cheatsheet/"/>
      <summary type="text">Python 依赖管理工具 Poetry 的常用命令速查：项目初始化、依赖管理、虚拟环境与发布流程。</summary>
      <content type="html"><![CDATA[<section><h3>1. 项目初始化与管理<a href="#1-项目初始化与管理"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>描述</th></tr></thead><tbody><tr><td>​<code>poetry new [project-name]</code>​</td><td>创建一个新的 Poetry 项目</td></tr><tr><td>​<code>poetry init</code>​</td><td>交互式创建或更新 <code>pyproject.toml</code>​文件</td></tr><tr><td>​<code>poetry install</code>​</td><td>安装项目依赖（根据 <code>pyproject.toml</code>​和 <code>poetry.lock</code>​）</td></tr><tr><td>​<code>poetry update</code>​</td><td>更新依赖到最新允许的版本并更新 <code>poetry.lock</code>​</td></tr><tr><td>​<code>poetry add [package]</code>​</td><td>添加依赖包</td></tr><tr><td>​<code>poetry add [package]@[version]</code>​</td><td>添加指定版本的依赖包</td></tr><tr><td>​<code>poetry add [package] --dev</code>​</td><td>添加开发依赖包</td></tr><tr><td>​<code>poetry remove [package]</code>​</td><td>移除依赖包</td></tr><tr><td>​<code>poetry show</code>​</td><td>显示已安装的依赖包</td></tr><tr><td>​<code>poetry show --tree</code>​</td><td>以树状结构显示依赖关系</td></tr><tr><td>​<code>poetry check</code>​</td><td>检查 <code>pyproject.toml</code>​文件的有效性</td></tr></tbody></table></section>
<section><h3>2. 虚拟环境管理<a href="#2-虚拟环境管理"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>描述</th></tr></thead><tbody><tr><td>​<code>poetry env list</code>​或 <code>poetry env list --full-path</code>​</td><td>列出所有 Poetry 虚拟环境</td></tr><tr><td>​<code>poetry env info</code>​</td><td>显示当前项目的虚拟环境信息</td></tr><tr><td>​<code>poetry env use [python-path]</code>​</td><td>为项目指定 Python 解释器</td></tr><tr><td>​<code>poetry env remove [env-name or path]</code>​</td><td>删除虚拟环境</td></tr><tr><td>​<code>poetry shell</code>​</td><td>激活项目的虚拟环境（进入交互式 shell）</td></tr><tr><td>​<code>poetry run [command]</code>​</td><td>在虚拟环境中运行命令，不激活 shell</td></tr></tbody></table></section>
<section><h3>3. 打包与发布<a href="#3-打包与发布"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>描述</th></tr></thead><tbody><tr><td>​<code>poetry build</code>​</td><td>构建项目为可分发的包（生成 <code>.tar.gz</code>​和 <code>.whl</code>​文件）</td></tr><tr><td>​<code>poetry publish</code>​</td><td>将包发布到 PyPI 或其他配置的仓库</td></tr><tr><td>​<code>poetry publish --repository [repo-name]</code>​</td><td>发布到指定的仓库</td></tr><tr><td>​<code>poetry config repositories.[repo-name] [repo-url]</code>​</td><td>配置私有仓库</td></tr></tbody></table></section>
<section><h3>4. 配置管理<a href="#4-配置管理"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>描述</th></tr></thead><tbody><tr><td>​<code>poetry config --list</code>​</td><td>列出所有配置</td></tr><tr><td>​<code>poetry config [key] [value]</code>​</td><td>设置配置值（如 <code>poetry config virtualenvs.create true</code>​）</td></tr><tr><td>​<code>poetry config --unset [key]</code>​</td><td>删除配置值</td></tr><tr><td>​<code>poetry self update</code>​</td><td>更新 Poetry 自身</td></tr></tbody></table></section>
<section><h3>5. 锁定文件管理<a href="#5-锁定文件管理"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>描述</th></tr></thead><tbody><tr><td>​<code>poetry lock</code>​</td><td>生成或更新 <code>poetry.lock</code>​文件（不安装依赖）</td></tr><tr><td>​<code>poetry lock --no-update</code>​</td><td>仅根据 <code>pyproject.toml</code>​重新生成 <code>poetry.lock</code>​，不更新依赖版本</td></tr></tbody></table></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/2026-09-monthly-review/</id>
      <title type="text">2026 年 9 月复盘：换赛道的第一个月</title>
      <published>2026-09-30T00:00:00.000Z</published>
      <updated>2026-09-30T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/2026-09-monthly-review/"/>
      <summary type="text">转岗到智能体方向的第一个月：两条产品线的架构设计从提出到通过评审，中间踩的坑、补的课，以及对『先写文档还是先写代码』的新认识。</summary>
      <content type="html"><![CDATA[<p>9 月发生了两件事：一是工作方向调整，从原来的业务开发转到智能体方向；二是手上的架构设计第一次完整走完了「设计—评审—进入开发」的全流程。月底回头看，这个月的关键词是<strong>节奏</strong>和<strong>文档</strong>。</p>
<section><h2>换赛道：从写功能到写架构<a href="#换赛道从写功能到写架构"><span>#</span></a></h2><p>月初转岗，方向是金融领域的 AI Agent。第一个感受是工作颗粒度变了：以前是拿到需求拆任务写代码，现在是先想清楚数据从哪来、模块怎么切、失败了怎么办，代码反而是最后落笔的。</p><p>这个月主要推了两条线：</p><ul>
<li><strong>问答式取数</strong>：让业务人员用自然语言查数据，背后是检索增强、语义解析和结果校验的组合。难点不在调模型，在于怎么让「答错了」可解释、可回退。</li>
<li><strong>尽职报告生成</strong>：给某大型银行做的报告类 Agent。文档类生成的坑在于模板是活的、输入是脏的，「可编辑」和「自动」之间的边界要提前划清，否则联调阶段会互相打架。</li>
</ul><p>两条线的架构设计都在月底前通过了评审，进入开发和联调阶段。BUG 数量也控制在个位数，算是给这个月收了个好尾。</p></section>
<section><h2>三件印象深的事<a href="#三件印象深的事"><span>#</span></a></h2><p><strong>1. 文档欠的债一定会还。</strong> 月中被抽了一整天补架构文档。补的过程中发现，之前凭记忆做的几个设计决策，实际实现已经跑偏了，是文档让我重新对齐了一次。以前觉得写文档是给别人的交代，现在觉得是给两周后失忆的自己留证据。</p><p><strong>2. 会开多了，代码就慢了。</strong> 有几天几乎全天在开会和对齐，晚上才摸键盘。不抱怨会议本身——跨部门协作确实需要——但我的结论是：重要的设计讨论要带结论出门，散会前把「谁、做什么、什么时候」说清楚，否则会议成本会翻倍。</p><p><strong>3. 「可编辑」是很贵的需求。</strong> 报告生成那条线，「模板可编辑」四个字背后是模板管理、版本控制、字段映射一整套东西。需求评审时多问一句「这个功能给谁用、多久用一次」，能把很多后续的返工提前砍掉。</p></section>
<section><h2>下个月<a href="#下个月"><span>#</span></a></h2><ul>
<li>两条线进入开发冲刺，重点是联调质量和错误处理。</li>
<li>把这个月沉淀的架构笔记整理出来，一部分发到博客上。</li>
<li>控制会议时间，保住整块的深度工作时段。</li>
</ul><hr /><p><em>复盘写在月底，不为给别人看，就为下个月的自己少踩一个坑。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/screen-guide/</id>
      <title type="text">Linux screen 命令详解</title>
      <published>2026-09-30T00:00:00.000Z</published>
      <updated>2026-09-30T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/screen-guide/"/>
      <summary type="text">screen 的常用命令与快捷键速查：会话创建、分离恢复、窗口操作，SSH 断线也不怕任务中断。</summary>
      <content type="html"><![CDATA[<section><h3><strong>Linux</strong> <strong>​<code>screen</code>​</strong>​ <strong>命令详解</strong><a href="#linux-screen-命令详解"><span>#</span></a></h3><p><code>screen</code>​ 是一个终端复用工具，允许你在单个终端窗口中创建多个虚拟终端会话，并在后台保持运行，即使断开 SSH 连接也不会中断任务。</p><hr /></section>
<section><h2><strong>常用</strong> <strong>​<code>screen</code>​</strong>​ <strong>命令</strong><a href="#常用-screen-命令"><span>#</span></a></h2><section><h3><strong>1. 基本操作</strong><a href="#1-基本操作"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>说明</th></tr></thead><tbody><tr><td>​<code>screen</code>​</td><td>启动一个新的 screen 会话</td></tr><tr><td>​<code>screen -S &lt;name&gt;</code>​</td><td>创建一个<strong>命名</strong>的 screen 会话（推荐）</td></tr><tr><td>​<code>screen -ls</code>​</td><td>列出所有 screen 会话</td></tr><tr><td>​<code>screen -r &lt;ID或name&gt;</code>​</td><td>恢复（重新连接）一个已存在的 screen 会话</td></tr><tr><td>​<code>screen -d &lt;ID或name&gt;</code>​</td><td><strong>分离（Detach）</strong>  一个 screen 会话（不关闭，仅退出）</td></tr><tr><td>​<code>screen -X -S &lt;ID或name&gt; quit</code>​</td><td><strong>强制关闭</strong> 某个 screen 会话</td></tr></tbody></table><hr /></section><section><h3><strong>2. 会话内操作（快捷键：<strong>​</strong>​<code>Ctrl + A</code>​</strong>​ <strong>后接命令）</strong><a href="#2-会话内操作快捷键ctrl--a-后接命令"><span>#</span></a></h3>

<table><thead><tr><th>快捷键</th><th>说明</th></tr></thead><tbody><tr><td>​<code>Ctrl + A + C</code>​</td><td>在当前会话中<strong>新建窗口</strong></td></tr><tr><td>​<code>Ctrl + A + N</code>​</td><td>切换到<strong>下一个窗口</strong></td></tr><tr><td>​<code>Ctrl + A + P</code>​</td><td>切换到<strong>上一个窗口</strong></td></tr><tr><td>​<code>Ctrl + A + 0-9</code>​</td><td>直接切换到<strong>第 N 个窗口</strong>（0-9）</td></tr><tr><td>​<code>Ctrl + A + D</code>​</td><td><strong>分离（Detach）</strong>  当前会话（不关闭，仅退出）</td></tr><tr><td>​<code>Ctrl + A + K</code>​</td><td><strong>强制关闭</strong> 当前窗口</td></tr><tr><td>​<code>Ctrl + A + [Space]</code>​</td><td>切换到下一个窗口（循环）</td></tr><tr><td>​<code>Ctrl + A + W</code>​</td><td>显示当前所有窗口列表</td></tr><tr><td>​<code>Ctrl + A + ?</code>​</td><td>查看所有快捷键帮助</td></tr></tbody></table><hr /></section><section><h3><strong>3. 高级用法</strong><a href="#3-高级用法"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>说明</th></tr></thead><tbody><tr><td>​<code>screen -dmS &lt;name&gt; &lt;command&gt;</code>​</td><td>在<strong>后台</strong>启动一个 screen 会话并运行命令</td></tr><tr><td>​<code>screen -x</code>​</td><td><strong>共享</strong> screen 会话（多人协作）</td></tr><tr><td>​<code>screen -r -d &lt;ID或name&gt;</code>​</td><td>强制恢复一个已连接的会话（先 Detach 再恢复）</td></tr></tbody></table><hr /></section></section>
<section><h2><strong>典型使用场景</strong><a href="#典型使用场景"><span>#</span></a></h2><ol>
<li>
<p><strong>长时间运行任务</strong>（如编译、下载、训练模型）：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>screen</span><span> </span><span>-S</span><span> </span><span>long_task</span></div></div><div><div><div>2</div></div><div><span>./run_long_script.sh</span></div></div><div><div><div>3</div></div><div><span># 按 Ctrl + A + D 退出，任务继续运行</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p><strong>恢复会话</strong>：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>screen</span><span> </span><span>-ls</span><span>  </span><span># 查看会话列表</span></div></div><div><div><div>2</div></div><div><span>screen</span><span> </span><span>-r</span><span> </span><span>long_task</span><span>  </span><span># 恢复</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p><strong>后台启动任务</strong>：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>screen</span><span> </span><span>-dmS</span><span> </span><span>my_task</span><span> </span><span>python3</span><span> </span><span>train.py</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p><strong>多窗口管理</strong>：</p>
<ul>
<li><code>Ctrl + A + C</code>​ 创建新窗口</li>
<li><code>Ctrl + A + N/P</code>​ 切换窗口</li>
</ul>
</li>
</ol><hr /></section>
<section><h2><strong>总结</strong><a href="#总结"><span>#</span></a></h2><ul>
<li><code>screen</code>​ 适合<strong>长时间运行任务</strong>，即使 SSH 断开也能恢复。</li>
<li>推荐使用 <code>-S &lt;name&gt;</code>​ 给会话命名，方便管理。</li>
<li><code>Ctrl + A + D</code>​ 是<strong>最常用的退出方式</strong>（不关闭会话）。</li>
<li><code>screen -ls</code>​ 查看所有会话，<code>screen -r</code>​ 恢复会话。</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/tmux-guide/</id>
      <title type="text">Tmux 详解：终端复用利器</title>
      <published>2026-09-28T00:00:00.000Z</published>
      <updated>2026-09-28T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/tmux-guide/"/>
      <summary type="text">Server / Session / Window / Pane 的层级结构，常用快捷键与会话管理技巧，适合远程服务器和长时间任务。</summary>
      <content type="html"><![CDATA[<section><h3><strong>Tmux 详解：终端复用利器</strong><a href="#tmux-详解终端复用利器"><span>#</span></a></h3><p>​<code>tmux</code>​（Terminal Multiplexer）是比 <code>screen</code>​ 更强大的终端复用工具，支持<strong>多窗口、多面板、会话持久化</strong>等功能，适合远程服务器管理、长时间任务运行和高效终端操作。</p><hr /></section>
<section><h2><strong>1. Tmux 核心概念</strong><a href="#1-tmux-核心概念"><span>#</span></a></h2><p>Tmux 采用 <strong>Server → Session → Window → Pane</strong> 的层级结构：</p><ul>
<li><strong>Server</strong>：管理所有会话的后台进程（<code>tmux</code>​ 启动时自动运行）。</li>
<li><strong>Session</strong>：一组窗口的集合（类似 <code>screen</code>​ 会话）。</li>
<li><strong>Window</strong>：单个会话中的多个标签页（类似浏览器标签）。</li>
<li><strong>Pane</strong>：窗口内的分屏（可横向/纵向切割）。</li>
</ul><hr /></section>
<section><h2><strong>2. 安装 Tmux</strong><a href="#2-安装-tmux"><span>#</span></a></h2><section><h3><strong>Linux (Debian/Ubuntu)</strong><a href="#linux-debianubuntu"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>tmux</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3><strong>Linux (CentOS/RHEL)</strong><a href="#linux-centosrhel"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>yum</span><span> </span><span>install</span><span> </span><span>tmux</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3><strong>macOS (Homebrew)</strong><a href="#macos-homebrew"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>brew</span><span> </span><span>install</span><span> </span><span>tmux</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2><strong>3. 基本操作</strong><a href="#3-基本操作"><span>#</span></a></h2><section><h3><strong>启动 Tmux</strong><a href="#启动-tmux"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>tmux</span><span>                     </span><span># 启动新会话（默认编号）</span></div></div><div><div><div>2</div></div><div><span>tmux</span><span> </span><span>new</span><span> </span><span>-s</span><span> </span><span>&lt;name&gt;</span><span>       </span><span># 启动命名会话（推荐）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3><strong>会话管理</strong><a href="#会话管理"><span>#</span></a></h3>

<table><thead><tr><th>命令</th><th>说明</th></tr></thead><tbody><tr><td>​<code>tmux ls</code>​</td><td>列出所有会话</td></tr><tr><td>​<code>tmux attach -t &lt;name&gt;</code>​</td><td>恢复指定会话</td></tr><tr><td>​<code>tmux kill-session -t &lt;name&gt;</code>​</td><td>关闭指定会话</td></tr><tr><td>​<code>tmux kill-server</code>​</td><td>关闭所有会话（慎用）</td></tr></tbody></table></section><section><h3><strong>快捷键（前缀键</strong> <strong>​<code>Ctrl+B</code>​</strong>​ <strong>）</strong><a href="#快捷键前缀键-ctrlb-"><span>#</span></a></h3><p>Tmux 的所有快捷键都需要先按 <strong>​<code>Ctrl+B</code>​</strong>​（前缀键），然后按后续命令键。</p><hr /></section></section>
<section><h2><strong>4. 窗口（Window）操作</strong><a href="#4-窗口window操作"><span>#</span></a></h2>

<table><thead><tr><th>快捷键</th><th>说明</th></tr></thead><tbody><tr><td>​<code>Ctrl+B C</code>​</td><td>创建新窗口</td></tr><tr><td>​<code>Ctrl+B N</code>​</td><td>切换到下一个窗口</td></tr><tr><td>​<code>Ctrl+B P</code>​</td><td>切换到上一个窗口</td></tr><tr><td>​<code>Ctrl+B 0-9</code>​</td><td>直接跳转到第 N 个窗口</td></tr><tr><td>​<code>Ctrl+B ,</code>​</td><td>重命名当前窗口</td></tr><tr><td>​<code>Ctrl+B &amp;</code>​</td><td>关闭当前窗口</td></tr></tbody></table><p>​<code>Ctrl+B </code>​d 分离</p><hr /></section>
<section><h2><strong>5. 面板（Pane）操作</strong><a href="#5-面板pane操作"><span>#</span></a></h2>

<table><thead><tr><th>快捷键</th><th>说明</th></tr></thead><tbody><tr><td>​<code>Ctrl+B %</code>​</td><td><strong>垂直分割</strong>面板</td></tr><tr><td>​<code>Ctrl+B "</code>​</td><td><strong>水平分割</strong>面板</td></tr><tr><td>​<code>Ctrl+B ↑↓←→</code>​</td><td>切换面板方向</td></tr><tr><td>​<code>Ctrl+B Z</code>​</td><td>最大化当前面板（再按恢复）</td></tr><tr><td>​<code>Ctrl+B X</code>​</td><td>关闭当前面板</td></tr><tr><td>​<code>Ctrl+B Space</code>​</td><td>切换面板布局</td></tr></tbody></table><hr /></section>
<section><h2><strong>6. 会话持久化</strong><a href="#6-会话持久化"><span>#</span></a></h2><p>Tmux 会话在 SSH 断开后仍然保持运行，重新连接后恢复：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>tmux</span><span> </span><span>attach</span><span> </span><span>-t</span><span> </span><span>&lt;name&gt;</span><span>   </span><span># 重新连接会话</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section>
<section><h2><strong>7. 高级功能</strong><a href="#7-高级功能"><span>#</span></a></h2><section><h3><strong>(1) 复制模式（类似 Vim）</strong><a href="#1-复制模式类似-vim"><span>#</span></a></h3><ul>
<li>​<code>Ctrl+B [</code>​ 进入复制模式</li>
<li>用 <code>↑↓←→</code>​ 移动光标，<code>Space</code>​ 开始选择，<code>Enter</code>​ 复制</li>
<li>​<code>Ctrl+B ]</code>​ 粘贴</li>
</ul></section><section><h3><strong>(2) 共享会话（多人协作）</strong><a href="#2-共享会话多人协作"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>tmux</span><span> </span><span>new</span><span> </span><span>-s</span><span> </span><span>shared</span><span>       </span><span># 创建共享会话</span></div></div><div><div><div>2</div></div><div><span>tmux</span><span> </span><span>attach</span><span> </span><span>-t</span><span> </span><span>shared</span><span>    </span><span># 其他人连接</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3><strong>(3) 配置文件</strong>  <strong>​<code>~/.tmux.conf</code>​</strong>​<a href="#3-配置文件--tmuxconf"><span>#</span></a></h3><p>自定义 Tmux 行为（如修改前缀键、主题等）：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 示例：更改前缀键为 Ctrl+A</span></div></div><div><div><div>2</div></div><div><span>set</span><span> </span><span>-g</span><span> </span><span>prefix</span><span> </span><span>C-a</span></div></div><div><div><div>3</div></div><div><span>unbind</span><span> </span><span>C-b</span></div></div><div><div><div>4</div></div><div><span>bind</span><span> </span><span>C-a</span><span> </span><span>send-prefix</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2><strong>8. Tmux vs. Screen</strong><a href="#8-tmux-vs-screen"><span>#</span></a></h2>

<table><thead><tr><th>功能</th><th>Tmux</th><th>Screen</th></tr></thead><tbody><tr><td><strong>分屏</strong></td><td>✔️（支持多面板）</td><td>❌（仅单窗口）</td></tr><tr><td><strong>会话管理</strong></td><td>✔️（更强大）</td><td>✔️</td></tr><tr><td><strong>快捷键</strong></td><td>​<code>Ctrl+B</code>​</td><td>​<code>Ctrl+A</code>​</td></tr><tr><td><strong>脚本化</strong></td><td>✔️（支持配置）</td><td>❌</td></tr><tr><td><strong>共享会话</strong></td><td>✔️</td><td>✔️</td></tr></tbody></table><hr /></section>
<section><h2><strong>9. 典型使用场景</strong><a href="#9-典型使用场景"><span>#</span></a></h2><ol>
<li><strong>远程服务器管理</strong>（SSH 断开后任务继续运行）</li>
<li><strong>多任务并行</strong>（编译、日志监控、代码编辑）</li>
<li><strong>团队协作</strong>（共享终端会话）</li>
<li><strong>高效终端操作</strong>（分屏、快捷键）</li>
</ol><hr /></section>
<section><h2><strong>总结</strong><a href="#总结"><span>#</span></a></h2><ul>
<li>
<p>​<strong>​<code>tmux</code>​</strong>​ <strong>比</strong> <strong>​<code>screen</code>​</strong>​ <strong>更强大</strong>，适合复杂终端管理。</p>
</li>
<li>
<p><strong>核心操作</strong>：</p>
<ul>
<li>​<code>tmux new -s &lt;name&gt;</code>​（创建会话）</li>
<li>​<code>Ctrl+B %</code>​ / <code>"</code>​（分屏）</li>
<li>​<code>tmux attach -t &lt;name&gt;</code>​（恢复会话）</li>
</ul>
</li>
<li>
<p><strong>推荐配置</strong>：修改 <code>~/.tmux.conf</code>​ 优化体验。</p>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/rust-ownership-guide/</id>
      <title type="text">Rust 所有权与核心概念完整指南</title>
      <published>2026-09-20T00:00:00.000Z</published>
      <updated>2026-09-20T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/rust-ownership-guide/"/>
      <summary type="text">从 &amp;str 与 String 的区别讲起，系统梳理 Rust 的所有权、借用、生命周期以及常见编译错误的成因。</summary>
      <content type="html"><![CDATA[<section><h3>1. 字符串字面量 <code>&amp;str</code><a href="#1-字符串字面量-str"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>s</span><span><span> </span><span>=</span><span> </span></span><span>"hello"</span><span>;  </span><span>// 类型：&amp;str</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>特点</strong>：</p><ul>
<li>存储在<strong>栈</strong>上（实际在二进制文件的只读内存中）</li>
<li><strong>不可变</strong></li>
<li>编译时已知大小</li>
<li>是对固定字符串的<strong>引用</strong>（借用）</li>
<li>零开销，最高效</li>
</ul></section>
<section><h3>2. <code>String</code> 类型<a href="#2-string-类型"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>s</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);  </span><span>// 类型：String</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>特点</strong>：</p><ul>
<li>数据存储在<strong>堆</strong>上</li>
<li><strong>可变</strong>（可以修改）</li>
<li>运行时动态分配内存</li>
<li>拥有数据的所有权</li>
<li>离开作用域时自动释放内存</li>
</ul></section>
<section><h3>3. 两者对比<a href="#3-两者对比"><span>#</span></a></h3>

<table><thead><tr><th>特性</th><th><code>&amp;str</code></th><th><code>String</code></th></tr></thead><tbody><tr><td>存储位置</td><td>栈（只读内存）</td><td>堆</td></tr><tr><td>可变性</td><td>不可变</td><td>可变</td></tr><tr><td>大小</td><td>编译时已知</td><td>运行时动态</td></tr><tr><td>所有权</td><td>借用</td><td>拥有</td></tr><tr><td>性能</td><td>最快</td><td>稍慢（堆分配）</td></tr></tbody></table></section>
<section><h3>4. 相互转换<a href="#4-相互转换"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// &amp;str -&gt; String</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>s1</span><span><span> </span><span>=</span><span> </span></span><span>"hello"</span><span>.</span><span>to_string</span><span>();</span></div></div><div><div><div>3</div></div><div><span>let</span><span> </span><span>s2</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// String -&gt; &amp;str</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>s3</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>let</span><span> </span><span>s4</span><span><span> </span><span>=</span><span> &amp;</span></span><span>s3</span><span>[</span><span>0</span><span>..</span><span>3</span><span>];  </span><span>// "hel"</span></div></div><div><div><div>8</div></div><div><span>let</span><span> </span><span>s5</span><span><span> </span><span>=</span><span> &amp;</span></span><span>s3</span><span>;         </span><span>// 自动转换</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section>
<section><h2>第二部分：可变性（<code>mut</code> 关键字）<a href="#第二部分可变性mut-关键字"><span>#</span></a></h2><section><h3>1. 基本概念<a href="#1-基本概念"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>x</span><span><span> </span><span>=</span><span> </span></span><span>5</span><span>;        </span><span>// 不可变（默认）</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>y</span><span><span> </span><span>=</span><span> </span></span><span>5</span><span>;    </span><span>// 可变</span></div></div><div><div><div>3</div></div><div><span>y</span><span><span> </span><span>=</span><span> </span></span><span>10</span><span>;           </span><span>// ✅ 可以修改</span></div></div><div><div><div>4</div></div><div><span>// x = 10;        // ❌ 编译错误！</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 为什么默认不可变？<a href="#2-为什么默认不可变"><span>#</span></a></h3><ul>
<li>防止意外修改</li>
<li>更容易推理代码</li>
<li>编译器可以做更多优化</li>
<li>内存安全保证</li>
</ul></section><section><h3>3. 可变性的应用场景<a href="#3-可变性的应用场景"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 变量绑定</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>count</span><span><span> </span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span>count</span><span><span> </span><span>+=</span><span> </span></span><span>1</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 2. 函数参数</span></div></div><div><div><div>6</div></div><div><span>fn</span><span> </span><span>increment</span><span>(</span><span>mut</span><span> </span><span>num</span><span>: </span><span>i32</span><span>) {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>num</span><span><span> </span><span>+=</span><span> </span></span><span>1</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// 3. String 的可变性</span></div></div><div><div><div>11</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>s</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>12</div></div><div><span>s</span><span>.</span><span>push_str</span><span>(</span><span>" world"</span><span>);  </span><span>// 可以修改</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>// 4. 结构体字段</span></div></div><div><div><div>15</div></div><div><span>struct</span><span> </span><span>User</span><span> {</span></div></div><div><div><div>16</div></div><div><span>    </span><span>name</span><span>: </span><span>String</span><span>,</span></div></div><div><div><div>17</div></div><div><span>    </span><span>age</span><span>: </span><span>u32</span><span>,</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>user</span><span><span> </span><span>=</span><span> </span></span><span>User</span><span> { </span><span>name</span><span>: </span><span>"Alice"</span><span>.</span><span>to_string</span><span>(), </span><span>age</span><span>: </span><span>30</span><span> };</span></div></div><div><div><div>20</div></div><div><span>user</span><span><span>.age </span><span>=</span><span> </span></span><span>31</span><span>;  </span><span>// 整个结构体必须是 mut</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>4. mut 与所有权的关系<a href="#4-mut-与所有权的关系"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>s</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>t</span><span><span> </span><span>=</span><span> &amp;</span></span><span>mut</span><span> </span><span>s</span><span>;  </span><span>// 可变引用</span></div></div><div><div><div>3</div></div><div><span>t</span><span>.</span><span>push_str</span><span>(</span><span>" world"</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// let u = &amp;mut s;  // ❌ 不能同时有多个可变引用</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2>第三部分：内存分配（栈 vs 堆）<a href="#第三部分内存分配栈-vs-堆"><span>#</span></a></h2><section><h3>1. 栈（Stack）<a href="#1-栈stack"><span>#</span></a></h3><p><strong>特点</strong>：</p><ul>
<li>后进先出（LIFO）</li>
<li>存储已知大小的数据</li>
<li>分配和释放极快</li>
<li>函数调用时自动管理</li>
</ul><p><strong>存储内容</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>a</span><span><span> </span><span>=</span><span> </span></span><span>5</span><span>;              </span><span>// 整数</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>true</span><span>;           </span><span>// 布尔</span></div></div><div><div><div>3</div></div><div><span>let</span><span> </span><span>c</span><span><span> </span><span>=</span><span> </span></span><span>'A'</span><span>;            </span><span>// 字符</span></div></div><div><div><div>4</div></div><div><span>let</span><span> </span><span>d</span><span><span> </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];      </span><span>// 数组（固定大小）</span></div></div><div><div><div>5</div></div><div><span>let</span><span> </span><span>e</span><span><span> </span><span>=</span><span> (</span></span><span>4</span><span>, </span><span>5.6</span><span>);       </span><span>// 元组（固定大小）</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>f</span><span><span> </span><span>=</span><span> </span></span><span>"hello"</span><span>;        </span><span>// 字符串字面量（&amp;str）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 堆（Heap）<a href="#2-堆heap"><span>#</span></a></h3><p><strong>特点</strong>：</p><ul>
<li>动态分配</li>
<li>存储未知大小或需要增长的数据</li>
<li>分配较慢</li>
<li>需要手动或自动（Rust）管理</li>
</ul><p><strong>存储内容</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>s</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);  </span><span>// 字符串内容</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>v</span><span><span> </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];          </span><span>// 向量内容</span></div></div><div><div><div>3</div></div><div><span>let</span><span> </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>42</span><span>);           </span><span>// Box 数据</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 内存布局图解<a href="#3-内存布局图解"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>s</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>栈（Stack）              堆（Heap）</span></div></div><div><div><div>2</div></div><div><span>┌─────────────┐         ┌─────────────┐</span></div></div><div><div><div>3</div></div><div><span>│  s (指针)    │────────&gt;│  "hello"    │</span></div></div><div><div><div>4</div></div><div><span>│  长度: 5     │         │   h e l l o │</span></div></div><div><div><div>5</div></div><div><span>│  容量: 5     │         └─────────────┘</span></div></div><div><div><div>6</div></div><div><span>└─────────────┘</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 可变性与存储位置无关<a href="#4-可变性与存储位置无关"><span>#</span></a></h3>

<table><thead><tr><th>变量</th><th>可变性</th><th>存储位置</th><th>示例</th></tr></thead><tbody><tr><td><code>let x = 5</code></td><td>不可变</td><td>栈</td><td>整数、布尔、字符</td></tr><tr><td><code>let mut x = 5</code></td><td>可变</td><td>栈</td><td>同上，但可改值</td></tr><tr><td><code>let s = String::from("hi")</code></td><td>不可变</td><td>栈指针→堆数据</td><td>字符串内容在堆上</td></tr><tr><td><code>let mut s = String::from("hi")</code></td><td>可变</td><td>栈指针→堆数据</td><td>可以修改堆上内容</td></tr></tbody></table><hr /></section></section>
<section><h2>第四部分：<code>Box&lt;T&gt;</code> 智能指针<a href="#第四部分boxt-智能指针"><span>#</span></a></h2><section><h3>1. 什么是 Box？<a href="#1-什么是-box"><span>#</span></a></h3><p><code>Box&lt;T&gt;</code> 是 Rust 提供的<strong>堆内存分配器</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>x</span><span><span> </span><span>=</span><span> </span></span><span>5</span><span>;              </span><span>// 存储在栈上</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>y</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>5</span><span>);    </span><span>// 存储在堆上，栈上只存指针</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 内存布局<a href="#2-内存布局"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>boxed</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>42</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>栈（Stack）              堆（Heap）</span></div></div><div><div><div>2</div></div><div><span>┌─────────────┐         ┌─────────────┐</span></div></div><div><div><div>3</div></div><div><span>│  boxed       │────────&gt;│    42       │</span></div></div><div><div><div>4</div></div><div><span>│  (指针)      │         │  (实际数据)  │</span></div></div><div><div><div>5</div></div><div><span>└─────────────┘         └─────────────┘</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. Box 的主要用途<a href="#3-box-的主要用途"><span>#</span></a></h3><section><h4>(1) 递归数据结构<a href="#1-递归数据结构"><span>#</span></a></h4><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>List</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>Cons</span><span>(</span><span>i32</span><span>, </span><span>Box</span><span>&lt;</span><span>List</span><span>&gt;),  </span><span>// Box 让递归成为可能</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Nil</span><span>,</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 如果不用 Box</span></div></div><div><div><div>7</div></div><div><span>// enum List {</span></div></div><div><div><div>8</div></div><div><span>//     Cons(i32, List),  // ❌ 编译错误：无限大小！</span></div></div><div><div><div>9</div></div><div><span>//     Nil,</span></div></div><div><div><div>10</div></div><div><span>// }</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h4>(2) 特征对象（多态）<a href="#2-特征对象多态"><span>#</span></a></h4><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>trait</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>fn</span><span> </span><span>sound</span><span>(&amp;</span><span>self</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>struct</span><span> </span><span>Dog</span><span>;</span></div></div><div><div><div>6</div></div><div><span>impl</span><span> </span><span>Animal</span><span> </span><span>for</span><span> </span><span>Dog</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>fn</span><span> </span><span>sound</span><span>(&amp;</span><span>self</span><span>) { </span><span>println!</span><span>(</span><span>"汪汪！"</span><span>); }</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>struct</span><span> </span><span>Cat</span><span>;</span></div></div><div><div><div>11</div></div><div><span>impl</span><span> </span><span>Animal</span><span> </span><span>for</span><span> </span><span>Cat</span><span> {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>fn</span><span> </span><span>sound</span><span>(&amp;</span><span>self</span><span>) { </span><span>println!</span><span>(</span><span>"喵喵！"</span><span>); }</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>let</span><span> </span><span>animals</span><span>: </span><span>Vec</span><span>&lt;</span><span>Box</span><span>&lt;</span><span>dyn</span><span> </span><span>Animal</span><span><span>&gt;&gt; </span><span>=</span><span> </span></span><span>vec!</span><span>[</span></div></div><div><div><div>16</div></div><div><span>    </span><span>Box</span><span>::</span><span>new</span><span>(</span><span>Dog</span><span>),</span></div></div><div><div><div>17</div></div><div><span>    </span><span>Box</span><span>::</span><span>new</span><span>(</span><span>Cat</span><span>),</span></div></div><div><div><div>18</div></div><div><span>];</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h4>(3) 让枚举大小固定<a href="#3-让枚举大小固定"><span>#</span></a></h4><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>Data</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>Small</span><span>(</span><span>Vec</span><span>&lt;</span><span>u8</span><span>&gt;),</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Large</span><span>(</span><span>Box</span><span>&lt;</span><span>Vec</span><span>&lt;</span><span>u8</span><span>&gt;&gt;),  </span><span>// Box 让枚举大小固定</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section><section><h3>4. Box 的自动解引用<a href="#4-box-的自动解引用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>boxed</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>vec!</span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>2</div></div><div><span>boxed</span><span>.</span><span>push</span><span>(</span><span>4</span><span>);     </span><span>// ✅ 自动解引用，直接使用</span></div></div><div><div><div>3</div></div><div><span>boxed</span><span>[</span><span>0</span><span><span>] </span><span>=</span><span> </span></span><span>42</span><span>;     </span><span>// ✅ 自动解引用</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 特殊情况需要手动解引用</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>5</span><span>);</span></div></div><div><div><div>7</div></div><div><span>*</span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>10</span><span>;           </span><span>// ✅ 修改值需要 *</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>5. Box vs 普通变量<a href="#5-box-vs-普通变量"><span>#</span></a></h3>

<table><thead><tr><th>特性</th><th>普通变量</th><th>Box</th></tr></thead><tbody><tr><td>存储位置</td><td>栈上</td><td>堆上</td></tr><tr><td>内存大小</td><td>实际数据大小</td><td>8字节（指针）</td></tr><tr><td>所有权</td><td>直接拥有数据</td><td>拥有堆上数据</td></tr><tr><td>性能</td><td>更快</td><td>稍慢（间接访问）</td></tr></tbody></table><hr /></section></section>
<section><h2>第五部分：<code>Vec&lt;T&gt;</code> 泛型集合<a href="#第五部分vect-泛型集合"><span>#</span></a></h2><section><h3>1. 基本概念<a href="#1-基本概念-1"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Vec</span><span>&lt;</span><span>u8</span><span>&gt;     </span><span>// 存储 u8 类型（无符号8位整数）</span></div></div><div><div><div>2</div></div><div><span>Vec</span><span>&lt;</span><span>i32</span><span>&gt;    </span><span>// 存储 i32 类型</span></div></div><div><div><div>3</div></div><div><span>Vec</span><span>&lt;</span><span>String</span><span>&gt; </span><span>// 存储 String 类型</span></div></div><div><div><div>4</div></div><div><span>Vec</span><span>&lt;</span><span>f64</span><span>&gt;    </span><span>// 存储 f64 类型</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 类型大小<a href="#2-类型大小"><span>#</span></a></h3>

<table><thead><tr><th>类型</th><th>单个元素大小</th><th>范围</th></tr></thead><tbody><tr><td><code>u8</code></td><td>1 字节</td><td>0 ~ 255</td></tr><tr><td><code>i32</code></td><td>4 字节</td><td>-2,147,483,648 ~ 2,147,483,647</td></tr><tr><td><code>f64</code></td><td>8 字节</td><td>±1.8e308（双精度）</td></tr><tr><td><code>String</code></td><td>24 字节（指针+长度+容量）</td><td>动态</td></tr></tbody></table></section><section><h3>3. 内存占用<a href="#3-内存占用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// Vec 本身在栈上占 24 字节</span></div></div><div><div><div>2</div></div><div><span>// 堆上数据 = 元素个数 × 每个元素大小</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>let</span><span> </span><span>v1</span><span>: </span><span>Vec</span><span>&lt;</span><span>u8</span><span><span>&gt; </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>0</span><span>; </span><span>1000</span><span>];   </span><span>// 堆上占 1000 字节</span></div></div><div><div><div>5</div></div><div><span>let</span><span> </span><span>v2</span><span>: </span><span>Vec</span><span>&lt;</span><span>i32</span><span><span>&gt; </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>0</span><span>; </span><span>1000</span><span>];  </span><span>// 堆上占 4000 字节</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 重要概念<a href="#4-重要概念"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// Vec 的数据在堆上，不是栈上！</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>huge_array</span><span><span> </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>0</span><span>; </span><span>1000000</span><span>];  </span><span>// 数据在堆上</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 转移所有权只复制指针（高效）</span></div></div><div><div><div>5</div></div><div><span>let</span><span> </span><span>vec1</span><span><span> </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>0</span><span>; </span><span>1000000</span><span>];</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>vec2</span><span><span> </span><span>=</span><span> </span></span><span>vec1</span><span>;  </span><span>// 只复制了3个字节（指针、长度、容量）</span></div></div><div><div><div>7</div></div><div><span>// vec1 不再可用</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// clone 会复制所有数据（慢）</span></div></div><div><div><div>10</div></div><div><span>let</span><span> </span><span>vec3</span><span><span> </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>0</span><span>; </span><span>1000000</span><span>];</span></div></div><div><div><div>11</div></div><div><span>let</span><span> </span><span>vec4</span><span><span> </span><span>=</span><span> </span></span><span>vec3</span><span>.</span><span>clone</span><span>();  </span><span>// 复制了100万个元素</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2>第六部分：枚举（<code>enum</code>）<a href="#第六部分枚举enum"><span>#</span></a></h2><section><h3>1. Rust enum vs Python enum<a href="#1-rust-enum-vs-python-enum"><span>#</span></a></h3><p><strong>Python</strong>：简单枚举值</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> enum </span><span>import</span><span> Enum</span></div></div><div><div><div>2</div></div><div><span>class</span><span><span> </span><span>Color</span><span>(</span><span>Enum</span><span>)</span></span><span>:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>RED</span><span> </span><span>=</span><span> </span><span>1</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>GREEN</span><span> </span><span>=</span><span> </span><span>2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Rust</strong>：强大的标签联合（可以携带数据）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>Color</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>Red</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Green</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>Blue</span><span>,</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>enum</span><span> </span><span>Message</span><span> {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>Quit</span><span>,                       </span><span>// 无数据</span></div></div><div><div><div>9</div></div><div><span>    </span><span>Move</span><span> { </span><span>x</span><span>: </span><span>i32</span><span>, </span><span>y</span><span>: </span><span>i32</span><span> },    </span><span>// 结构体数据</span></div></div><div><div><div>10</div></div><div><span>    </span><span>Write</span><span>(</span><span>String</span><span>),              </span><span>// 单个数据</span></div></div><div><div><div>11</div></div><div><span>    </span><span>ChangeColor</span><span>(</span><span>u8</span><span>, </span><span>u8</span><span>, </span><span>u8</span><span>),    </span><span>// 元组数据</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 枚举变体<a href="#2-枚举变体"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>List</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>Cons</span><span>(</span><span>i32</span><span>, </span><span>Box</span><span>&lt;</span><span>List</span><span>&gt;),  </span><span>// 变体1：包含值和下一个节点</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Nil</span><span>,                   </span><span>// 变体2：空链表</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 使用变体</span></div></div><div><div><div>7</div></div><div><span>let</span><span> </span><span>node</span><span><span> </span><span>=</span><span> </span></span><span>List</span><span>::</span><span>Cons</span><span>(</span><span>5</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span><span>(</span><span>List</span><span>::</span></span><span>Nil</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 使用 <code>use</code> 简化路径<a href="#3-使用-use-简化路径"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 完整路径</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>list</span><span><span> </span><span>=</span><span> </span></span><span>List</span><span>::</span><span>Cons</span><span>(</span><span>1</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span><span>(</span><span>List</span><span>::</span></span><span>Nil</span><span>));</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 导入后简化</span></div></div><div><div><div>5</div></div><div><span>use</span><span><span> </span><span>List</span><span>::{</span></span><span>Cons</span><span>, </span><span>Nil</span><span>};</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>list</span><span><span> </span><span>=</span><span> </span></span><span>Cons</span><span>(</span><span>1</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Nil</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 匹配枚举<a href="#4-匹配枚举"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>match</span><span> </span><span>small_data</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>Data</span><span>::</span><span>Small</span><span>(</span><span>vec</span><span>) =&gt; </span><span>println!</span><span>(</span><span>"小数据：{:?}"</span><span>, </span><span>vec</span><span>),</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Data</span><span>::</span><span>Large</span><span>(</span><span>vec</span><span>) =&gt; </span><span>println!</span><span>(</span><span>"大数据：长度 {}"</span><span>, </span><span>vec</span><span>.</span><span>len</span><span>()),</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2>第七部分：Cons 链表<a href="#第七部分cons-链表"><span>#</span></a></h2><section><h3>1. Cons 是什么？<a href="#1-cons-是什么"><span>#</span></a></h3><p>Cons 来自 Lisp 语言，是 “Constructor” 的缩写：</p><ul>
<li><strong>Cons</strong> = 一个节点，包含<strong>当前值</strong>和<strong>指向下一个节点的指针</strong></li>
<li><strong>Nil</strong> = 空链表（结束标志）</li>
</ul></section><section><h3>2. 链表定义<a href="#2-链表定义"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>List</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>Cons</span><span>(</span><span>i32</span><span>, </span><span>Box</span><span>&lt;</span><span>List</span><span>&gt;),  </span><span>// 值 + 指向下一个节点的指针</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Nil</span><span>,                   </span><span>// 空</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 链表：1 -&gt; 2 -&gt; 3 -&gt; Nil</span></div></div><div><div><div>7</div></div><div><span>// Cons(1, Cons(2, Cons(3, Nil)))</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 构建链表<a href="#3-构建链表"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 从尾部开始构建</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>list</span><span><span> </span><span>=</span><span> </span></span><span>Cons</span><span>(</span><span>1</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Cons</span><span>(</span><span>2</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Cons</span><span>(</span><span>3</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Nil</span><span>))))));</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 逐步构建</span></div></div><div><div><div>5</div></div><div><span>let</span><span> </span><span>tail</span><span><span> </span><span>=</span><span> </span></span><span>Cons</span><span>(</span><span>3</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Nil</span><span>));</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>mid</span><span><span> </span><span>=</span><span> </span></span><span>Cons</span><span>(</span><span>2</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>tail</span><span>));</span></div></div><div><div><div>7</div></div><div><span>let</span><span> </span><span>head</span><span><span> </span><span>=</span><span> </span></span><span>Cons</span><span>(</span><span>1</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>mid</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 内存布局<a href="#4-内存布局"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>栈                          堆</span></div></div><div><div><div>2</div></div><div><span>┌──────────────┐           ┌──────────────┐</span></div></div><div><div><div>3</div></div><div><span>│ list (头部)   │──────────&gt;│ Cons(1)     │</span></div></div><div><div><div>4</div></div><div><span>└──────────────┘           │  next ──────┐│</span></div></div><div><div><div>5</div></div><div><span><span>                           </span></span><span>└─────────────┴│</span></div></div><div><div><div>6</div></div><div><span><span>                                           </span></span><span>▼</span></div></div><div><div><div>7</div></div><div><span><span>                           </span></span><span>┌──────────────┐</span></div></div><div><div><div>8</div></div><div><span><span>                           </span></span><span>│ Cons(2)     │</span></div></div><div><div><div>9</div></div><div><span><span>                           </span></span><span>│  next ──────┐│</span></div></div><div><div><div>10</div></div><div><span><span>                           </span></span><span>└─────────────┴│</span></div></div><div><div><div>11</div></div><div><span><span>                                           </span></span><span>▼</span></div></div><div><div><div>12</div></div><div><span><span>                           </span></span><span>┌──────────────┐</span></div></div><div><div><div>13</div></div><div><span><span>                           </span></span><span>│ Cons(3)     │</span></div></div><div><div><div>14</div></div><div><span><span>                           </span></span><span>│  next ──────┐│</span></div></div><div><div><div>15</div></div><div><span><span>                           </span></span><span>└─────────────┴│</span></div></div><div><div><div>16</div></div><div><span><span>                                           </span></span><span>▼</span></div></div><div><div><div>17</div></div><div><span><span>                           </span></span><span>┌──────────────┐</span></div></div><div><div><div>18</div></div><div><span><span>                           </span></span><span>│ Nil         │</span></div></div><div><div><div>19</div></div><div><span><span>                           </span></span><span>└──────────────┘</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>5. 更优雅的构建方式<a href="#5-更优雅的构建方式"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 使用标准库</span></div></div><div><div><div>2</div></div><div><span>use</span><span><span> </span><span>std</span><span>::</span><span>collections</span><span>::</span></span><span>LinkedList</span><span>;</span></div></div><div><div><div>3</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>list</span><span><span> </span><span>=</span><span> </span></span><span>LinkedList</span><span>::</span><span>new</span><span>();</span></div></div><div><div><div>4</div></div><div><span>list</span><span>.</span><span>extend</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 使用 Vec（推荐！）</span></div></div><div><div><div>7</div></div><div><span>let</span><span> </span><span>list</span><span><span> </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];  </span><span>// 90% 的情况用 Vec 就够了</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2>第八部分：操作符 <code>.</code> vs <code>::</code><a href="#第八部分操作符--vs-"><span>#</span></a></h2><section><h3>1. 核心规则<a href="#1-核心规则"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// . 用于实例（已经创建的对象）</span></div></div><div><div><div>2</div></div><div><span>// :: 用于类型/模块（命名空间）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. <code>.</code> 点操作符<a href="#2--点操作符"><span>#</span></a></h3><p><strong>用于实例的字段和方法</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>struct</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>name</span><span>: </span><span>String</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>age</span><span>: </span><span>u32</span><span>,</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>impl</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>fn</span><span> </span><span>greet</span><span>(&amp;</span><span>self</span><span>) {</span></div></div><div><div><div>8</div></div><div><span>        </span><span>println!</span><span>(</span><span>"你好，我是{}"</span><span>, </span><span>self</span><span>.name);</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>let</span><span> </span><span>p</span><span><span> </span><span>=</span><span> </span></span><span>Person</span><span> { </span><span>name</span><span>: </span><span>"Alice"</span><span>.</span><span>to_string</span><span>(), </span><span>age</span><span>: </span><span>30</span><span> };</span></div></div><div><div><div>13</div></div><div><span>p</span><span>.</span><span>greet</span><span>();          </span><span>// ✅ 调用实例方法</span></div></div><div><div><div>14</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>p</span><span>.name);  </span><span>// ✅ 访问实例字段</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. <code>::</code> 双冒号操作符<a href="#3--双冒号操作符"><span>#</span></a></h3><p><strong>用于类型级别的东西</strong>：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 关联函数（类似静态方法）</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>s</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>3</div></div><div><span>let</span><span> </span><span>v</span><span><span> </span><span>=</span><span> </span></span><span>Vec</span><span>::</span><span>new</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 2. 枚举变体</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>c</span><span><span> </span><span>=</span><span> </span></span><span>Color</span><span>::</span><span>Red</span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 3. 模块路径</span></div></div><div><div><div>9</div></div><div><span>use</span><span><span> </span><span>std</span><span>::</span><span>collections</span><span>::</span></span><span>HashMap</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 4. 关联常量</span></div></div><div><div><div>12</div></div><div><span>struct</span><span> </span><span>Config</span><span>;</span></div></div><div><div><div>13</div></div><div><span>impl</span><span> </span><span>Config</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>const</span><span> </span><span>VERSION</span><span>: </span><span>u32</span><span><span> </span><span>=</span><span> </span></span><span>1</span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>Config</span><span>::</span><span>VERSION</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>4. 完整对比表<a href="#4-完整对比表"><span>#</span></a></h3>

<table><thead><tr><th>操作符</th><th>使用场景</th><th>示例</th></tr></thead><tbody><tr><td><code>.</code></td><td>访问实例字段</td><td><code>person.name</code></td></tr><tr><td><code>.</code></td><td>调用实例方法</td><td><code>person.greet()</code></td></tr><tr><td><code>.</code></td><td>访问元组索引</td><td><code>tuple.0</code></td></tr><tr><td><code>::</code></td><td>调用关联函数</td><td><code>String::from("hi")</code></td></tr><tr><td><code>::</code></td><td>访问关联常量</td><td><code>MyStruct::VERSION</code></td></tr><tr><td><code>::</code></td><td>访问枚举变体</td><td><code>Color::Red</code></td></tr><tr><td><code>::</code></td><td>模块路径</td><td><code>std::collections::HashMap</code></td></tr></tbody></table></section><section><h3>5. 从 Python 角度理解<a href="#5-从-python-角度理解"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Config</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>DEFAULT</span><span> </span><span>=</span><span> </span><span>100</span><span>  </span><span># 类属性（类似关联常量）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>value</span></span><span>):</span></div></div><div><div><div>5</div></div><div><span>        </span><span>self</span><span><span>.value </span><span>=</span><span> value  </span></span><span># 实例属性</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>print</span><span><span>(Config.</span><span>DEFAULT</span><span>)        </span></span><span># 类属性访问</span></div></div><div><div><div>8</div></div><div><span><span>config </span><span>=</span><span> </span><span>Config</span><span>(</span></span><span>42</span><span>)</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(config.value)          </span><span># 实例属性访问</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>struct</span><span> </span><span>Config</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>value</span><span>: </span><span>i32</span><span>,</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>impl</span><span> </span><span>Config</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>const</span><span> </span><span>DEFAULT</span><span>: </span><span>i32</span><span><span> </span><span>=</span><span> </span></span><span>100</span><span>;  </span><span>// 关联常量</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>Config</span><span>::</span><span>DEFAULT</span><span>);  </span><span>// :: 访问</span></div></div><div><div><div>10</div></div><div><span>let</span><span> </span><span>config</span><span><span> </span><span>=</span><span> </span></span><span>Config</span><span> { </span><span>value</span><span>: </span><span>42</span><span> };</span></div></div><div><div><div>11</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>config</span><span>.value);     </span><span>// . 访问</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2>第九部分：解引用运算符 <code>*</code><a href="#第九部分解引用运算符-"><span>#</span></a></h2><section><h3>1. 基本概念<a href="#1-基本概念-2"><span>#</span></a></h3><p><code>*</code> 是<strong>解引用运算符</strong>，用于”跟随指针拿到数据”。</p></section><section><h3>2. 使用场景<a href="#2-使用场景"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 栈上的引用</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>x</span><span><span> </span><span>=</span><span> </span></span><span>42</span><span>;</span></div></div><div><div><div>3</div></div><div><span>let</span><span> </span><span>r</span><span><span> </span><span>=</span><span> &amp;</span></span><span>x</span><span>;</span></div></div><div><div><div>4</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, *</span><span>r</span><span>);  </span><span>// 解引用，拿到 42</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 2. 堆上的数据（Box）</span></div></div><div><div><div>7</div></div><div><span>let</span><span> </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>100</span><span>);</span></div></div><div><div><div>8</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, *</span><span>b</span><span>);  </span><span>// 解引用，拿出 100</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 自动解引用<a href="#3-自动解引用"><span>#</span></a></h3><p>Rust 会自动解引用，大多数情况不需要手动 <code>*</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>boxed</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>vec!</span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>2</div></div><div><span>boxed</span><span>.</span><span>push</span><span>(</span><span>4</span><span>);        </span><span>// ✅ 自动解引用</span></div></div><div><div><div>3</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>boxed</span><span>[</span><span>0</span><span>]);  </span><span>// ✅ 自动解引用</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 何时需要手动 <code>*</code><a href="#4-何时需要手动-"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 修改 Box 的值</span></div></div><div><div><div>2</div></div><div><span>let</span><span> </span><span>mut</span><span> </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>5</span><span>);</span></div></div><div><div><div>3</div></div><div><span>*</span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>10</span><span>;  </span><span>// ✅ 必须用 *</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 2. 取出所有权</span></div></div><div><div><div>6</div></div><div><span>let</span><span> </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span><span>(</span><span>String</span><span>::</span></span><span>from</span><span>(</span><span>"hello"</span><span>));</span></div></div><div><div><div>7</div></div><div><span>let</span><span> </span><span>s</span><span><span> </span><span>=</span><span> *</span></span><span>b</span><span>;  </span><span>// ✅ 取出堆上的 String</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 3. 自定义类型的访问</span></div></div><div><div><div>10</div></div><div><span>struct</span><span> </span><span>Point</span><span> { </span><span>x</span><span>: </span><span>i32</span><span>, </span><span>y</span><span>: </span><span>i32</span><span> }</span></div></div><div><div><div>11</div></div><div><span>let</span><span> </span><span>p</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>Point</span><span> { </span><span>x</span><span>: </span><span>1</span><span>, </span><span>y</span><span>: </span><span>2</span><span> });</span></div></div><div><div><div>12</div></div><div><span>println!</span><span>(</span><span>"{}"</span><span>, (*</span><span>p</span><span>).x);  </span><span>// 可以，但 p.x 更常见</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>5. 解引用总结<a href="#5-解引用总结"><span>#</span></a></h3>

<table><thead><tr><th>操作符</th><th>作用</th><th>何时需要</th></tr></thead><tbody><tr><td><code>*</code></td><td>解引用（跟随指针）</td><td>修改 Box 的值、取出所有权</td></tr><tr><td><code>.</code></td><td>自动解引用</td><td>调用方法时自动处理</td></tr><tr><td><code>[]</code></td><td>索引（自动解引用）</td><td>访问 Vec 等容器元素</td></tr></tbody></table><hr /></section></section>
<section><h2>第十部分：完整代码示例<a href="#第十部分完整代码示例"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 字符串类型</span></div></div><div><div><div>2</div></div><div><span>fn</span><span> </span><span>string_examples</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>let</span><span> </span><span>s1</span><span><span> </span><span>=</span><span> </span></span><span>"hello"</span><span>;  </span><span>// &amp;str，栈上</span></div></div><div><div><div>4</div></div><div><span>    </span><span>let</span><span> </span><span>s2</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"world"</span><span>);  </span><span>// String，堆上</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>let</span><span> </span><span>mut</span><span> </span><span>s3</span><span><span> </span><span>=</span><span> </span></span><span>String</span><span>::</span><span>from</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>    </span><span>s3</span><span>.</span><span>push_str</span><span>(</span><span>" world"</span><span>);  </span><span>// 可以修改</span></div></div><div><div><div>8</div></div><div><span>    </span><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>s3</span><span>);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 2. Box 使用</span></div></div><div><div><div>12</div></div><div><span>fn</span><span> </span><span>box_examples</span><span>() {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>let</span><span> </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>42</span><span>);</span></div></div><div><div><div>14</div></div><div><span>    </span><span>println!</span><span>(</span><span>"{}"</span><span>, *</span><span>b</span><span>);  </span><span>// 解引用</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>let</span><span> </span><span>mut</span><span> </span><span>b2</span><span><span> </span><span>=</span><span> </span></span><span>Box</span><span>::</span><span>new</span><span>(</span><span>10</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>*</span><span>b2</span><span><span> </span><span>=</span><span> </span></span><span>20</span><span>;  </span><span>// 修改</span></div></div><div><div><div>18</div></div><div><span>    </span><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>b2</span><span>);  </span><span>// 自动解引用</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>// 3. 枚举和链表</span></div></div><div><div><div>22</div></div><div><span>enum</span><span> </span><span>List</span><span> {</span></div></div><div><div><div>23</div></div><div><span>    </span><span>Cons</span><span>(</span><span>i32</span><span>, </span><span>Box</span><span>&lt;</span><span>List</span><span>&gt;),</span></div></div><div><div><div>24</div></div><div><span>    </span><span>Nil</span><span>,</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>fn</span><span> </span><span>list_examples</span><span>() {</span></div></div><div><div><div>28</div></div><div><span>    </span><span>use</span><span><span> </span><span>List</span><span>::{</span></span><span>Cons</span><span>, </span><span>Nil</span><span>};</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>    </span><span>let</span><span> </span><span>list</span><span><span> </span><span>=</span><span> </span></span><span>Cons</span><span>(</span><span>1</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Cons</span><span>(</span><span>2</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Cons</span><span>(</span><span>3</span><span><span>, </span><span>Box</span><span>::</span></span><span>new</span><span>(</span><span>Nil</span><span>))))));</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>    </span><span>// 遍历</span></div></div><div><div><div>33</div></div><div><span>    </span><span>let</span><span> </span><span>mut</span><span> </span><span>current</span><span><span> </span><span>=</span><span> &amp;</span></span><span>list</span><span>;</span></div></div><div><div><div>34</div></div><div><span>    </span><span>while</span><span> </span><span>let</span><span> </span><span>Cons</span><span>(</span><span>value</span><span>, </span><span>next</span><span><span>) </span><span>=</span><span> </span></span><span>current</span><span> {</span></div></div><div><div><div>35</div></div><div><span>        </span><span>print!</span><span>(</span><span>"{} -&gt; "</span><span>, </span><span>value</span><span>);</span></div></div><div><div><div>36</div></div><div><span>        </span><span>current</span><span><span> </span><span>=</span><span> </span></span><span>next</span><span>;</span></div></div><div><div><div>37</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>38</div></div><div><span>    </span><span>println!</span><span>(</span><span>"Nil"</span><span>);</span></div></div><div><div><div>39</div></div><div><span>}</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>// 4. Vec 使用</span></div></div><div><div><div>42</div></div><div><span>fn</span><span> </span><span>vec_examples</span><span>() {</span></div></div><div><div><div>43</div></div><div><span>    </span><span>let</span><span> </span><span>mut</span><span> </span><span>v</span><span><span> </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>44</div></div><div><span>    </span><span>v</span><span>.</span><span>push</span><span>(</span><span>4</span><span>);</span></div></div><div><div><div>45</div></div><div><span>    </span><span>v</span><span>[</span><span>0</span><span><span>] </span><span>=</span><span> </span></span><span>10</span><span>;</span></div></div><div><div><div>46</div></div><div><span>    </span><span>println!</span><span>(</span><span>"{:?}"</span><span>, </span><span>v</span><span>);  </span><span>// [10, 2, 3, 4]</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>    </span><span>// Vec 数据在堆上</span></div></div><div><div><div>49</div></div><div><span>    </span><span>let</span><span> </span><span>big</span><span><span> </span><span>=</span><span> </span></span><span>vec!</span><span>[</span><span>0</span><span>; </span><span>1000000</span><span>];</span></div></div><div><div><div>50</div></div><div><span>    </span><span>let</span><span> </span><span>moved</span><span><span> </span><span>=</span><span> </span></span><span>big</span><span>;  </span><span>// 所有权转移，只复制指针</span></div></div><div><div><div>51</div></div><div><span>    </span><span>// println!("{}", big[0]);  // ❌ big 已失效</span></div></div><div><div><div>52</div></div><div><span>}</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div><span>// 5. 结构体和关联常量</span></div></div><div><div><div>55</div></div><div><span>struct</span><span> </span><span>Config</span><span> {</span></div></div><div><div><div>56</div></div><div><span>    </span><span>pub</span><span> </span><span>value</span><span>: </span><span>i32</span><span>,</span></div></div><div><div><div>57</div></div><div><span>}</span></div></div><div><div><div>58</div></div><div>
</div></div><div><div><div>59</div></div><div><span>impl</span><span> </span><span>Config</span><span> {</span></div></div><div><div><div>60</div></div><div><span>    </span><span>const</span><span> </span><span>DEFAULT</span><span>: </span><span>i32</span><span><span> </span><span>=</span><span> </span></span><span>100</span><span>;</span></div></div><div><div><div>61</div></div><div>
</div></div><div><div><div>62</div></div><div><span>    </span><span>fn</span><span> </span><span>new</span><span>(</span><span>value</span><span>: </span><span>i32</span><span>) -&gt; </span><span>Self</span><span> {</span></div></div><div><div><div>63</div></div><div><span>        </span><span>Config</span><span> { </span><span>value</span><span> }</span></div></div><div><div><div>64</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>65</div></div><div>
</div></div><div><div><div>66</div></div><div><span>    </span><span>fn</span><span> </span><span>get_value</span><span>(&amp;</span><span>self</span><span>) -&gt; </span><span>i32</span><span> {</span></div></div><div><div><div>67</div></div><div><span>        </span><span>self</span><span>.value</span></div></div><div><div><div>68</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>69</div></div><div><span>}</span></div></div><div><div><div>70</div></div><div>
</div></div><div><div><div>71</div></div><div><span>fn</span><span> </span><span>struct_examples</span><span>() {</span></div></div><div><div><div>72</div></div><div><span>    </span><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>Config</span><span>::</span><span>DEFAULT</span><span>);  </span><span>// :: 访问关联常量</span></div></div><div><div><div>73</div></div><div>
</div></div><div><div><div>74</div></div><div><span>    </span><span>let</span><span> </span><span>config</span><span><span> </span><span>=</span><span> </span></span><span>Config</span><span>::</span><span>new</span><span>(</span><span>42</span><span>);     </span><span>// :: 调用关联函数</span></div></div><div><div><div>75</div></div><div><span>    </span><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>config</span><span>.value);     </span><span>// . 访问字段</span></div></div><div><div><div>76</div></div><div><span>    </span><span>println!</span><span>(</span><span>"{}"</span><span>, </span><span>config</span><span>.</span><span>get_value</span><span>()); </span><span>// . 调用方法</span></div></div><div><div><div>77</div></div><div><span>}</span></div></div><div><div><div>78</div></div><div>
</div></div><div><div><div>79</div></div><div><span>// 6. main 函数</span></div></div><div><div><div>80</div></div><div><span>fn</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>81</div></div><div><span>    </span><span>string_examples</span><span>();</span></div></div><div><div><div>82</div></div><div><span>    </span><span>box_examples</span><span>();</span></div></div><div><div><div>83</div></div><div><span>    </span><span>list_examples</span><span>();</span></div></div><div><div><div>84</div></div><div><span>    </span><span>vec_examples</span><span>();</span></div></div><div><div><div>85</div></div><div><span>    </span><span>struct_examples</span><span>();</span></div></div><div><div><div>86</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><hr /></section>
<section><h2>总结：核心要点速查<a href="#总结核心要点速查"><span>#</span></a></h2><section><h3>内存管理<a href="#内存管理"><span>#</span></a></h3><ul>
<li><strong>栈</strong>：固定大小，快速，自动管理</li>
<li><strong>堆</strong>：动态大小，较慢，需要显式管理（Rust 自动清理）</li>
</ul></section><section><h3>所有权规则<a href="#所有权规则"><span>#</span></a></h3><ol>
<li>每个值都有一个所有者</li>
<li>同一时间只能有一个所有者</li>
<li>所有者离开作用域时值被丢弃</li>
</ol></section><section><h3>可变性<a href="#可变性"><span>#</span></a></h3><ul>
<li>默认不可变（<code>let</code>）</li>
<li>需要可变时用 <code>mut</code></li>
<li>可变性与存储位置无关</li>
</ul></section><section><h3>字符串<a href="#字符串"><span>#</span></a></h3><ul>
<li><code>&amp;str</code>：不可变，栈上，借用</li>
<li><code>String</code>：可变，堆上，拥有所有权</li>
</ul></section><section><h3>智能指针<a href="#智能指针"><span>#</span></a></h3><ul>
<li><code>Box&lt;T&gt;</code>：堆分配，拥有所有权</li>
<li>用于递归类型、特征对象、固定枚举大小</li>
</ul></section><section><h3>集合<a href="#集合"><span>#</span></a></h3><ul>
<li><code>Vec&lt;T&gt;</code>：动态数组，数据在堆上</li>
<li><code>LinkedList</code>：双向链表，标准库提供</li>
</ul></section><section><h3>操作符<a href="#操作符"><span>#</span></a></h3><ul>
<li><code>.</code>：实例级别（字段、方法）</li>
<li><code>::</code>：类型级别（关联函数、常量、枚举变体）</li>
<li><code>*</code>：解引用（跟随指针）</li>
</ul></section><section><h3>枚举<a href="#枚举"><span>#</span></a></h3><ul>
<li>强大的标签联合</li>
<li>可以携带数据</li>
<li>变体可以用 <code>use</code> 导入</li>
</ul></section></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/langchain-vectorstore-search/</id>
      <title type="text">LangChain VectorStore 的几种检索方式</title>
      <published>2026-09-14T00:00:00.000Z</published>
      <updated>2026-09-14T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/langchain-vectorstore-search/"/>
      <summary type="text">similarity_search、带分数检索、MMR 等几种向量检索方式的差异和适用场景。</summary>
      <content type="html"><![CDATA[<p>👉 <strong>最常用</strong>，按向量相似度排序，返回最接近的文档。</p>
<ul>
<li>
<p><strong>参数</strong>：</p>
<ul>
<li>​<code>query</code>​: 查询文本</li>
<li>​<code>k</code>​: 返回的文档数</li>
</ul>
</li>
<li>
<p><strong>作用</strong>：找出“最相似”的内容，适合大多数问答场景。</p>
</li>
<li>
<p><strong>缺点</strong>：不会考虑“查询和文档的匹配相关性权重”，只看向量。</p>
</li>
</ul>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>docs </span><span>=</span><span> vectorstore.</span><span>similarity_search</span><span>(</span></span><span>"拜登的气候政策"</span><span>, </span><span>k</span><span>=</span><span>3</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<hr />
<section><h2>2. <code>similarity_search_with_score</code>​<a href="#2-similarity_search_with_score"><span>#</span></a></h2><p>👉 和 <code>similarity_search</code>​ 一样，但会返回 <strong>相似度分数</strong>。</p><ul>
<li>
<p><strong>作用</strong>：</p>
<ul>
<li>可根据分数过滤低相关性文档；</li>
<li>适合需要“阈值控制”的任务（比如只要相似度 &gt;0.8 的结果）。</li>
</ul>
</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>docs </span><span>=</span><span> vectorstore.</span><span>similarity_search_with_score</span><span>(</span></span><span>"气候变化"</span><span>, </span><span>k</span><span>=</span><span>3</span><span>)</span></div></div><div><div><div>2</div></div><div><span>for</span><span> doc, score </span><span>in</span><span> docs:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(doc.page_content, score)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section>
<section><h2>3. <code>max_marginal_relevance_search</code>​ (MMR)<a href="#3-max_marginal_relevance_search-mmr"><span>#</span></a></h2><p>👉 <strong>最大边际相关性检索</strong>，在相似度的基础上增加“多样性”。</p><ul>
<li>
<p><strong>作用</strong>：</p>
<ul>
<li>避免检索结果过于重复；</li>
<li>适合用户需要“覆盖不同角度”的问题，比如“中美关系”时返回中方和美方新闻，而不是全是中方的。</li>
</ul>
</li>
<li>
<p><strong>机制</strong>：</p>
<ul>
<li>在相似度高的候选中，挑一部分相似但彼此差异大的文档。</li>
</ul>
</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>docs </span><span>=</span><span> vectorstore.</span><span>max_marginal_relevance_search</span><span>(</span></span><span>"国际气候合作"</span><span>, </span><span>k</span><span>=</span><span>5</span><span>, </span><span>fetch_k</span><span>=</span><span>20</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section>
<section><h2>4. <code>similarity_search_by_vector</code>​<a href="#4-similarity_search_by_vector"><span>#</span></a></h2><p>👉 如果你 <strong>自己已经有了 query 的向量</strong>（比如外部 embedding 模型算的），可以直接用这个接口。</p><ul>
<li><strong>作用</strong>：绕过 LangChain 的 embedding，直接用外部向量进行搜索。</li>
<li><strong>适合场景</strong>：比如你有多模态输入（图像、音频 → embedding），但想在同一个 Milvus 里检索文本。</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>embedding_vector </span><span>=</span><span> [</span></span><span>0.12</span><span><span>, </span><span>-</span></span><span>0.33</span><span>, </span><span>0.88</span><span><span>, </span><span>...</span><span>]  </span></span><span># 自己算的</span></div></div><div><div><div>2</div></div><div><span><span>docs </span><span>=</span><span> vectorstore.</span><span>similarity_search_by_vector</span><span>(embedding_vector, </span></span><span>k</span><span>=</span><span>3</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section>
<section><h2>5. <code>as_retriever</code>​<a href="#5-as_retriever"><span>#</span></a></h2><p>👉 把向量库封装成一个 <strong>Retriever</strong>，供 RAG / QA Chain 使用。</p><ul>
<li>
<p><strong>优势</strong>：</p>
<ul>
<li>统一接口，可以随意切换 FAISS、Milvus、PGVector；</li>
<li>可以配合 <code>RetrievalQA</code>​、<code>ConversationalRetrievalChain</code>​ 等。</li>
</ul>
</li>
<li>
<p><strong>检索模式可配置</strong>（例如 similarity / MMR）：</p>
</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>retriever </span><span>=</span><span> vectorstore.</span><span>as_retriever</span><span>(</span></span><span>search_type</span><span>=</span><span>"mmr"</span><span>, </span><span>search_kwargs</span><span><span>=</span><span>{</span></span><span>"k"</span><span>: </span><span>5</span><span>})</span></div></div><div><div><div>2</div></div><div><span><span>docs </span><span>=</span><span> retriever.</span><span>get_relevant_documents</span><span>(</span></span><span>"拜登在联合国说了什么"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section>
<section><h1>📝 总结对比<a href="#-总结对比"><span>#</span></a></h1>

<table><thead><tr><th>方法</th><th>功能</th><th>适合场景</th></tr></thead><tbody><tr><td>​<code>similarity_search</code>​</td><td>按相似度取Top-K</td><td>默认、通用</td></tr><tr><td>​<code>similarity_search_with_score</code>​</td><td>相似度+分数</td><td>需要阈值过滤</td></tr><tr><td>​<code>max_marginal_relevance_search</code>​</td><td>相似+多样性</td><td>避免结果重复、覆盖不同角度</td></tr><tr><td>​<code>similarity_search_by_vector</code>​</td><td>直接用外部向量查</td><td>多模态 / 自定义 embedding</td></tr><tr><td>​<code>as_retriever</code>​</td><td>转换成Retriever</td><td>RAG、QA链集成</td></tr></tbody></table></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/langchain-prompt-template/</id>
      <title type="text">LangChain PromptTemplate 详解：把 Prompt 当代码管理</title>
      <published>2026-09-11T00:00:00.000Z</published>
      <updated>2026-09-11T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/langchain-prompt-template/"/>
      <summary type="text">用模板把 Prompt 从字符串常量升级为可复用、可组合、可结构化输出的模块：占位符、FewShot、ChatPromptTemplate 与输出解析器的配合。</summary>
      <content type="html"><![CDATA[<p>PromptTemplate 是 LangChain 的核心模块之一，作用是 <strong>组织和动态生成 Prompt</strong>。<br />
它解决的问题是：Prompt 不能写死，需要和用户输入 / 任务上下文结合，保持复用和一致性。</p>
<hr />
<section><h2>1. PromptTemplate 的核心作用<a href="#1-prompttemplate-的核心作用"><span>#</span></a></h2><ol>
<li><strong>模板化 Prompt</strong>：用 <code>{}</code>​ 占位，把变量和固定内容分离。</li>
<li><strong>动态渲染</strong>：运行时把用户输入填充进去。</li>
<li><strong>减少重复代码</strong>：把 Prompt 逻辑集中管理，而不是散落在代码里。</li>
<li><strong>结构化输出</strong>：结合 parser，可以要求模型输出 JSON / YAML 等格式。</li>
</ol><hr /></section>
<section><h2>2. 基本用法<a href="#2-基本用法"><span>#</span></a></h2><section><h3>（1）最简单的创建方式<a href="#1最简单的创建方式"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.prompts </span><span>import</span><span> PromptTemplate</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>template </span><span>=</span><span> </span></span><span>"把以下中文翻译成英文: </span><span>{text}</span><span>"</span></div></div><div><div><div>4</div></div><div><span><span>prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(template)</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span># 渲染</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(prompt.</span><span>format</span><span>(</span></span><span>text</span><span>=</span><span>"你好，世界"</span><span>))</span></div></div><div><div><div>8</div></div><div><span># =&gt; "把以下中文翻译成英文: 你好，世界"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section><section><h3>（2）带多个变量<a href="#2带多个变量"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>template </span><span>=</span><span> </span></span><span>"请写一首关于 </span><span>{animal}</span><span> 和 </span><span>{place}</span><span> 的诗"</span></div></div><div><div><div>2</div></div><div><span><span>prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(template)</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>print</span><span><span>(prompt.</span><span>format</span><span>(</span></span><span>animal</span><span>=</span><span>"小猫"</span><span>, </span><span>place</span><span>=</span><span>"月亮"</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>请写一首关于 小猫 和 月亮 的诗</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section><section><h3>（3）显式指定输入变量<a href="#3显式指定输入变量"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>prompt </span><span>=</span><span> </span><span>PromptTemplate</span><span>(</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>input_variables</span><span><span>=</span><span>[</span></span><span>"product"</span><span>, </span><span>"style"</span><span>],</span></div></div><div><div><div>3</div></div><div><span>    </span><span>template</span><span>=</span><span>"请写一个关于 </span><span>{product}</span><span> 的广告文案，风格是 </span><span>{style}</span><span>"</span></div></div><div><div><div>4</div></div><div><span>)</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>print</span><span><span>(prompt.</span><span>format</span><span>(</span></span><span>product</span><span>=</span><span>"咖啡"</span><span>, </span><span>style</span><span>=</span><span>"幽默"</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section></section>
<section><h2>3. 高级功能<a href="#3-高级功能"><span>#</span></a></h2><section><h3>（1）PromptTemplate + Partial（部分固定）<a href="#1prompttemplate--partial部分固定"><span>#</span></a></h3><p>有时候某些变量是 <strong>固定的</strong>，可以先“绑定”住。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>"把以下内容翻译成 </span><span>{language}</span><span>: </span><span>{text}</span><span>"</span></div></div><div><div><div>3</div></div><div><span>)</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 固定 language</span></div></div><div><div><div>6</div></div><div><span><span>partial_prompt </span><span>=</span><span> prompt.</span><span>partial</span><span>(</span></span><span>language</span><span>=</span><span>"English"</span><span>)</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(partial_prompt.</span><span>format</span><span>(</span></span><span>text</span><span>=</span><span>"早上好"</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section><section><h3>（2）多层 Prompt 组合<a href="#2多层-prompt-组合"><span>#</span></a></h3><p>你可以把小模板组合成复杂的 Prompt。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>intro_prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(</span></span><span>"用户问题是: </span><span>{question}</span><span>"</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>task_prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(</span></span><span>"请根据以下问题生成 SQL: </span><span>{question}</span><span>"</span><span>)</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>full_prompt </span><span>=</span><span> intro_prompt.</span><span>format</span><span>(</span></span><span>question</span><span>=</span><span>"查询今天销量"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(full_prompt)</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(task_prompt.</span><span>format</span><span>(</span></span><span>question</span><span>=</span><span>"查询今天销量"</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section><section><h3>（3）和输出解析器结合<a href="#3和输出解析器结合"><span>#</span></a></h3><p>LangChain 提供 <strong>OutputParser</strong>，可以结合 PromptTemplate，指导模型输出 JSON、列表等结构化结果。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.output_parsers </span><span>import</span><span> ResponseSchema, StructuredOutputParser</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>schemas </span><span>=</span><span> [</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>ResponseSchema</span><span>(</span><span>name</span><span>=</span><span>"summary"</span><span>, </span><span>description</span><span>=</span><span>"文本总结"</span><span>),</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>ResponseSchema</span><span>(</span><span>name</span><span>=</span><span>"keywords"</span><span>, </span><span>description</span><span>=</span><span>"关键词"</span><span>),</span></div></div><div><div><div>6</div></div><div><span>]</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>parser </span><span>=</span><span> StructuredOutputParser.</span><span>from_response_schemas</span><span>(schemas)</span></span></div></div><div><div><div>9</div></div><div><span><span>format_instructions </span><span>=</span><span> parser.</span><span>get_format_instructions</span><span>()</span></span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(</span></span><span>"""</span></div></div><div><div><div>12</div></div><div><span>请分析以下文本：</span></div></div><div><div><div>13</div></div><div><span>{text}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>请严格按照以下格式输出：</span></div></div><div><div><div>16</div></div><div><span>{format_instructions}</span></div></div><div><div><div>17</div></div><div><span>"""</span><span>)</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>print</span><span><span>(prompt.</span><span>format</span><span>(</span></span><span>text</span><span>=</span><span>"今天股市上涨，投资人情绪积极"</span><span>, </span><span>format_instructions</span><span><span>=</span><span>format_instructions))</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这样 Prompt 会明确告诉模型输出 JSON，并能用 <code>parser.parse()</code>​ 解析。</p><hr /></section><section><h3>（4）Few-shot Prompting<a href="#4few-shot-prompting"><span>#</span></a></h3><p>PromptTemplate 可以和 <strong>示例库（FewShotPromptTemplate）</strong>  配合，让模型参考样例。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.prompts </span><span>import</span><span> FewShotPromptTemplate</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>examples </span><span>=</span><span> [</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>{</span><span>"word"</span><span>: </span><span>"猫"</span><span>, </span><span>"translation"</span><span>: </span><span>"cat"</span><span>},</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>{</span><span>"word"</span><span>: </span><span>"狗"</span><span>, </span><span>"translation"</span><span>: </span><span>"dog"</span><span>},</span></div></div><div><div><div>6</div></div><div><span>]</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>example_template </span><span>=</span><span> </span></span><span>"中文: </span><span>{word}</span><span> -&gt; 英文: </span><span>{translation}</span><span>"</span></div></div><div><div><div>9</div></div><div><span><span>example_prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(example_template)</span></span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>prompt </span><span>=</span><span> </span><span>FewShotPromptTemplate</span><span>(</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>examples</span><span><span>=</span><span>examples,</span></span></div></div><div><div><div>13</div></div><div><span>    </span><span>example_prompt</span><span><span>=</span><span>example_prompt,</span></span></div></div><div><div><div>14</div></div><div><span>    </span><span>suffix</span><span>=</span><span>"中文: </span><span>{input}</span><span> -&gt; 英文:"</span><span>,</span></div></div><div><div><div>15</div></div><div><span>    </span><span>input_variables</span><span><span>=</span><span>[</span></span><span>"input"</span><span>]</span></div></div><div><div><div>16</div></div><div><span>)</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>print</span><span><span>(prompt.</span><span>format</span><span>(</span></span><span>input</span><span>=</span><span>"苹果"</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>输出大致为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>中文: 猫 -&gt; 英文: cat</span></div></div><div><div><div>2</div></div><div><span>中文: 狗 -&gt; 英文: dog</span></div></div><div><div><div>3</div></div><div><span>中文: 苹果 -&gt; 英文:</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section><section><h3>（5）动态选择模板（Selector）<a href="#5动态选择模板selector"><span>#</span></a></h3><p>如果你的输入场景复杂，可以让 LangChain 自动挑选最合适的模板。</p><p>例如：</p><ul>
<li>用户输入太短 → 用简单 Prompt</li>
<li>用户输入很长 → 用总结型 Prompt</li>
</ul><p>（这里可以结合 <code>LengthBasedExampleSelector</code>​ 等工具）</p><hr /></section></section>
<section><h2>4. PromptTemplate 的常见技巧<a href="#4-prompttemplate-的常见技巧"><span>#</span></a></h2><ol>
<li>
<p><strong>用大括号</strong>  <strong>​<code>{{ }}</code>​</strong> ​ <strong>转义</strong><br />
如果你要在模板里输出固定的花括号（比如 JSON），要用双层：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>template </span><span>=</span><span> </span></span><span>"输出 JSON: </span><span>{{</span><span>'a': '</span><span>{value}</span><span>'</span><span>}}</span><span>"</span></div></div><div><div><div>2</div></div><div><span><span>prompt </span><span>=</span><span> PromptTemplate.</span><span>from_template</span><span>(template)</span></span></div></div><div><div><div>3</div></div><div><span>print</span><span><span>(prompt.</span><span>format</span><span>(</span></span><span>value</span><span>=</span><span>"测试"</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>✅ 否则会被误认为是占位符。</p>
</li>
<li>
<p><strong>加入格式约束</strong></p>
<ul>
<li>在 Prompt 里明确说明输出必须是 JSON / Markdown / 表格。</li>
<li>给出样例输出，效果更稳定。</li>
</ul>
</li>
<li>
<p><strong>分层管理 Prompt</strong></p>
<ul>
<li>用不同的 PromptTemplate 管不同任务（翻译 / 总结 / 检索）。</li>
<li>在 Chain 里组合，减少重复。</li>
</ul>
</li>
<li>
<p><strong>调试 Prompt</strong></p>
<ul>
<li>​<code>prompt.format()</code>​ 先看看渲染结果，再丢给 LLM。</li>
<li>建议用 LangSmith 或日志系统跟踪实际 Prompt。</li>
</ul>
</li>
</ol><hr /></section>
<section><h2>5. 总结<a href="#5-总结"><span>#</span></a></h2><ul>
<li><strong>PromptTemplate</strong> = 占位 + 模板渲染。</li>
<li>支持：单变量、多变量、部分固定、FewShot、解析器、动态选择。</li>
<li>核心技巧：转义、格式约束、样例提示、日志调试。</li>
<li>价值：让 Prompt <strong>结构化、复用、可控</strong>，避免硬编码。</li>
</ul><p>如何输出json</p></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/langchain-tools/</id>
      <title type="text">LangChain 的 Tools 体系：给 LLM 装上手和脚</title>
      <published>2026-09-08T00:00:00.000Z</published>
      <updated>2026-09-08T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/langchain-tools/"/>
      <summary type="text">Tool 的接口定义、结构化工具（StructuredTool）、工具集与工具包的组织方式，以及 Agent 选择工具的原理。</summary>
      <content type="html"><![CDATA[<p>LangChain 的核心之一是 <strong>Agent + Tools</strong>。<br />
它的理念是：LLM 本身是生成文本的能力，但<strong>很多任务需要调用外部工具/系统</strong>，比如搜索、计算、数据库查询、API 调用。</p>
<hr />
<section><h2>1. 基本概念<a href="#1-基本概念"><span>#</span></a></h2><section><h3>（1）Tool<a href="#1tool"><span>#</span></a></h3><ul>
<li>
<p><strong>定义</strong>：一个 Python 对象，封装了外部能力（函数、API、数据库等）。</p>
</li>
<li>
<p><strong>接口</strong>：至少包含两个属性：</p>
<ul>
<li>​<code>name</code>​：工具名</li>
<li>​<code>func</code>​：执行函数</li>
<li>​<code>description</code>​：给 LLM 说明工具做什么</li>
</ul>
</li>
<li>
<p>LLM 会根据 prompt + description 决定调用哪个工具。</p>
</li>
</ul><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.tools </span><span>import</span><span> Tool</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>def</span><span> </span><span>calculator</span><span>(</span><span>query</span><span>:</span><span> </span><span>str</span><span>) -&gt; </span><span>str</span><span>:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span> </span><span>str</span><span>(</span><span>eval</span><span>(query))</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>calc_tool </span><span>=</span><span> </span><span>Tool</span><span>(</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>name</span><span>=</span><span>"Calculator"</span><span>,</span></div></div><div><div><div>8</div></div><div><span>    </span><span>func</span><span><span>=</span><span>calculator,</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>description</span><span>=</span><span>"用于执行数学运算，例如 2+2"</span></div></div><div><div><div>10</div></div><div><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section><section><h3>（2）Agent<a href="#2agent"><span>#</span></a></h3><ul>
<li>
<p>Agent 是一个 <strong>智能决策者</strong>，根据用户输入：</p>
<ol>
<li>思考（LLM分析问题）</li>
<li>决定调用哪个 Tool</li>
<li>执行 Tool</li>
<li>收集结果并继续思考</li>
</ol>
</li>
<li>
<p>LangChain 内置多种 agent 类型：</p>
<ul>
<li>​<code>ZeroShotAgent</code>​</li>
<li>​<code>ReActAgent</code>​</li>
<li>​<code>ConversationalAgent</code>​</li>
<li>​<code>StructuredToolAgent</code>​（结合输出解析器）</li>
</ul>
</li>
</ul><hr /></section></section>
<section><h2>2. 工具使用方式<a href="#2-工具使用方式"><span>#</span></a></h2><section><h3>（1）简单工具调用<a href="#1简单工具调用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.agents </span><span>import</span><span> initialize_agent</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>tools </span><span>=</span><span> [calc_tool]</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>agent </span><span>=</span><span> </span><span>initialize_agent</span><span>(tools, llm, </span></span><span>agent</span><span>=</span><span>"zero-shot-react-description"</span><span>, </span><span>verbose</span><span>=</span><span>True</span><span>)</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>agent.</span><span>run</span><span>(</span></span><span>"计算 123 * 456"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>56088</span></div></div></code></pre><div><div></div><div></div></div></figure></div><hr /></section><section><h3>（2）结合多工具<a href="#2结合多工具"><span>#</span></a></h3><ul>
<li>可以同时注册 <strong>搜索、计算、数据库查询、API</strong>。</li>
<li>LLM 会选择最合适的工具：</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.agents </span><span>import</span><span> Tool</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>search_tool </span><span>=</span><span> </span><span>Tool</span><span>(</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>name</span><span>=</span><span>"Search"</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>func</span><span>=</span><span>lambda</span><span> </span><span>x</span><span>: </span><span>"搜索结果: xxx"</span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>description</span><span>=</span><span>"搜索互联网以获取最新信息"</span></div></div><div><div><div>7</div></div><div><span>)</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>agent </span><span>=</span><span> </span><span>initialize_agent</span><span>([calc_tool, search_tool], llm, </span></span><span>agent</span><span>=</span><span>"zero-shot-react-description"</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>agent.</span><span>run</span><span>(</span></span><span>"查找今天的天气并计算温度差"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>LLM 会先调用 <code>Search</code>​，然后 <code>Calculator</code>​，再返回答案。</p><hr /></section></section>
<section><h2>3. 多步骤工具链 (MCP / Multi-Tool Chain)<a href="#3-多步骤工具链-mcp--multi-tool-chain"><span>#</span></a></h2><p>你提到 <strong>MCP</strong>（Multi-Chain / Multi-Tool Pipeline）概念，其实 LangChain 的 <strong>Agent + Tools + Chains</strong> 就可以实现类似功能：</p><ul>
<li>
<p><strong>Multi-Step Chain</strong>（SequentialChain / RouterChain）可以串联多个工具调用流程。</p>
</li>
<li>
<p><strong>Agent + Tools</strong> 可以动态选择工具和顺序，形成“多工具任务处理管线”。</p>
</li>
<li>
<p>目前 LangChain 官方没有叫“<strong>MCP</strong>”的模块，但完全可以通过：</p>
<ul>
<li><strong>RouterChain + Agents + Tool</strong></li>
<li><strong>SequentialChain + Multi-Tool Agent</strong><br />
来实现多工具并行或串行调用。</li>
</ul>
</li>
</ul><hr /><section><h3>（3）示意：MCP 风格工作流<a href="#3示意mcp-风格工作流"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.chains </span><span>import</span><span> SequentialChain</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 假设有三个工具</span></div></div><div><div><div>4</div></div><div><span><span>tools </span><span>=</span><span> [calc_tool, search_tool]</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span># Step1: 查询问题相关背景</span></div></div><div><div><div>7</div></div><div><span><span>search_chain </span><span>=</span><span> </span><span>LLMChain</span><span>(</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>llm</span><span><span>=</span><span>llm,</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>prompt</span><span><span>=</span><span>PromptTemplate.</span><span>from_template</span><span>(</span></span><span>"请搜索问题背景: </span><span>{query}</span><span>"</span><span>),</span></div></div><div><div><div>10</div></div><div><span>    </span><span>output_key</span><span>=</span><span>"search_result"</span></div></div><div><div><div>11</div></div><div><span>)</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># Step2: 计算结果</span></div></div><div><div><div>14</div></div><div><span><span>calc_chain </span><span>=</span><span> </span><span>LLMChain</span><span>(</span></span></div></div><div><div><div>15</div></div><div><span>    </span><span>llm</span><span><span>=</span><span>llm,</span></span></div></div><div><div><div>16</div></div><div><span>    </span><span>prompt</span><span><span>=</span><span>PromptTemplate.</span><span>from_template</span><span>(</span></span><span>"根据背景 </span><span>{search_result}</span><span> 计算结果: </span><span>{query}</span><span>"</span><span>),</span></div></div><div><div><div>17</div></div><div><span>    </span><span>output_key</span><span>=</span><span>"calc_result"</span></div></div><div><div><div>18</div></div><div><span>)</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>workflow </span><span>=</span><span> </span><span>SequentialChain</span><span>(</span></span><span>chains</span><span><span>=</span><span>[search_chain, calc_chain], </span></span><span>input_variables</span><span><span>=</span><span>[</span></span><span>"query"</span><span>], </span><span>output_variables</span><span><span>=</span><span>[</span></span><span>"calc_result"</span><span>])</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span><span>workflow.</span><span>invoke</span><span>({</span></span><span>"query"</span><span>: </span><span>"计算今天的温差"</span><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>这里每一步都可以调用不同的工具。</li>
<li>实际上就是 <strong>多工具、多步骤执行管线</strong>，可以视作 MCP 的实现方式。</li>
</ul><hr /></section></section>
<section><h2>4. 特点总结<a href="#4-特点总结"><span>#</span></a></h2>

<table><thead><tr><th>功能</th><th>描述</th><th>MCP 实现可能性</th></tr></thead><tbody><tr><td>Tool</td><td>封装外部能力</td><td>✅ 可以多工具注册</td></tr><tr><td>Agent</td><td>LLM + 工具决策者</td><td>✅ 自动选择工具</td></tr><tr><td>SequentialChain</td><td>串联工具/LLM链</td><td>✅ 可以做多步骤 MCP</td></tr><tr><td>RouterChain</td><td>输入路由选择不同工具</td><td>✅ 可实现条件分支 MCP</td></tr><tr><td>StructuredToolAgent</td><td>输出解析 + 多工具</td><td>✅ 更稳定 MCP</td></tr></tbody></table><hr /><section><h3>✅ 小结<a href="#-小结"><span>#</span></a></h3><ul>
<li>
<p>LangChain <strong>原生不叫 MCP</strong>，但其架构完全可以实现多工具、多步骤、多分支的 <strong>Multi-Tool Pipeline</strong>。</p>
</li>
<li>
<p>MCP 在 LangChain 中可通过 <strong>Agent + Tools + Chain</strong> 实现：</p>
<ul>
<li>多工具注册 → Agent 决策调用 → 链式或分支流程执行 → 输出聚合。</li>
</ul>
</li>
</ul></section></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/langchain-agent-basics/</id>
      <title type="text">LangChain Agent 入门：LLM + 工具集 + 推理策略</title>
      <published>2026-09-05T00:00:00.000Z</published>
      <updated>2026-09-05T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/langchain-agent-basics/"/>
      <summary type="text">Agent 的组成部分、Zero-shot / ReAct / Plan-and-Act 策略对比，以及工具设计、内存、token 控制方面的注意事项。</summary>
      <content type="html"><![CDATA[<p>在 LangChain 中，<strong>Agent（智能代理）</strong>  是一个可以根据用户输入<strong>动态选择工具并执行操作</strong>的模型。<br />
它不是单纯调用 LLM，而是能做决策：</p>
<ol>
<li>识别用户意图</li>
<li>选择合适的工具（Tool）</li>
<li>执行工具操作</li>
<li>根据工具输出更新推理</li>
<li>最终输出答案</li>
</ol>
<p><strong>核心思想</strong>：Agent = LLM + 工具集 + 推理策略</p>
<hr />
<section><h2><strong>二、Agent 的组成部分</strong><a href="#二agent-的组成部分"><span>#</span></a></h2><ol>
<li>
<p><strong>LLM</strong>：语言模型</p>
<ul>
<li>决策核心</li>
<li>支持 OpenAI、Claude、Llama 等</li>
</ul>
</li>
<li>
<p><strong>Tools（工具）</strong> ：Agent 可用的外部接口</p>
<ul>
<li>Web 搜索（<code>SerpAPI</code>​、<code>GoogleSearchAPI</code>​）</li>
<li>数据库查询（SQLDatabaseChain）</li>
<li>文件读取（<code>TextLoader</code>​ + <code>VectorDB</code>​）</li>
<li>自定义工具（任何函数，只需符合 <code>tool</code>​ 接口）</li>
</ul>
</li>
<li>
<p><strong>Agent 类型 / 策略</strong>：LLM 如何调用工具</p>
<ul>
<li><strong>Zero-shot agent</strong>：不依赖示例，直接用 prompt 决策</li>
<li><strong>ReAct agent</strong>：结合推理（Reasoning）+ 行动（Action）</li>
<li><strong>Conversational agent</strong>：适合多轮对话</li>
<li><strong>Plan-and-Act agent</strong>（新版）：先规划步骤再执行</li>
</ul>
</li>
<li>
<p><strong>Memory（可选）</strong> ：存储上下文，尤其是多轮对话中 Agent 的知识</p>
<ul>
<li>​<code>ConversationBufferMemory</code>​</li>
<li>​<code>ConversationSummaryMemory</code>​</li>
<li>​<code>VectorStoreMemory</code>​</li>
</ul>
</li>
</ol><hr /></section>
<section><h2><strong>三、基本使用流程</strong><a href="#三基本使用流程"><span>#</span></a></h2><p>假设我们想做一个查询天气的 Agent：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.agents </span><span>import</span><span> initialize_agent, Tool</span></div></div><div><div><div>2</div></div><div><span>from</span><span> langchain.llms </span><span>import</span><span> OpenAI</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 1. 定义 LLM</span></div></div><div><div><div>5</div></div><div><span><span>llm </span><span>=</span><span> </span><span>OpenAI</span><span>(</span></span><span>temperature</span><span>=</span><span>0</span><span>)</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 2. 定义工具</span></div></div><div><div><div>8</div></div><div><span>def</span><span> </span><span>get_weather</span><span>(</span><span>city</span><span>:</span><span> </span><span>str</span><span>) -&gt; </span><span>str</span><span>:</span></div></div><div><div><div>9</div></div><div><span>    </span><span>return</span><span> </span><span>f</span><span>"</span><span>{</span><span>city</span><span>}</span><span> 今天晴，25度"</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>weather_tool </span><span>=</span><span> </span><span>Tool</span><span>(</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>name</span><span>=</span><span>"Weather"</span><span>,</span></div></div><div><div><div>13</div></div><div><span>    </span><span>func</span><span><span>=</span><span>get_weather,</span></span></div></div><div><div><div>14</div></div><div><span>    </span><span>description</span><span>=</span><span>"获取指定城市的天气"</span></div></div><div><div><div>15</div></div><div><span>)</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span># 3. 初始化 Agent</span></div></div><div><div><div>18</div></div><div><span><span>agent </span><span>=</span><span> </span><span>initialize_agent</span><span>(</span></span></div></div><div><div><div>19</div></div><div><span>    </span><span>tools</span><span><span>=</span><span>[weather_tool],</span></span></div></div><div><div><div>20</div></div><div><span>    </span><span>llm</span><span><span>=</span><span>llm,</span></span></div></div><div><div><div>21</div></div><div><span>    </span><span>agent</span><span>=</span><span>"zero-shot-react-description"</span><span>,  </span><span># Zero-shot ReAct agent</span></div></div><div><div><div>22</div></div><div><span>    </span><span>verbose</span><span>=</span><span>True</span></div></div><div><div><div>23</div></div><div><span>)</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span># 4. 执行</span></div></div><div><div><div>26</div></div><div><span><span>agent.</span><span>run</span><span>(</span></span><span>"请告诉我北京今天的天气"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>核心要点</strong>：</p><ul>
<li>​<code>agent="zero-shot-react-description"</code>​ 表示使用 ReAct 风格策略</li>
<li>​<code>Tool</code>​ 必须包含 <code>name</code>​, <code>func</code>​, <code>description</code>​</li>
<li>Agent 会根据输入自动选择工具执行</li>
</ul><hr /></section>
<section><h2><strong>四、注意事项</strong><a href="#四注意事项"><span>#</span></a></h2><section><h3><strong>1. 工具设计</strong><a href="#1-工具设计"><span>#</span></a></h3><ul>
<li>​<code>description</code>​ 至关重要：LLM 通过描述选择工具</li>
<li>工具函数尽量保持幂等（相同输入输出一致）</li>
<li>对复杂工具可加安全检查，避免危险操作</li>
</ul></section><section><h3><strong>2. Agent 类型选择</strong><a href="#2-agent-类型选择"><span>#</span></a></h3><ul>
<li><strong>Zero-shot</strong>：灵活，但易出错</li>
<li><strong>ReAct</strong>：推荐，能处理复杂任务，多步推理</li>
<li><strong>Plan-and-Act</strong>：适合长任务，先规划步骤再执行</li>
</ul></section><section><h3><strong>3. 内存 &amp; 多轮对话</strong><a href="#3-内存--多轮对话"><span>#</span></a></h3><ul>
<li>对话 Agent 必须配置 <code>memory</code>​</li>
<li>注意 token 限制，避免长对话 context 超出模型上下文</li>
</ul></section><section><h3><strong>4. Prompt 与输出控制</strong><a href="#4-prompt-与输出控制"><span>#</span></a></h3><ul>
<li>可以自定义 <code>agent_prompt</code>​ 控制 LLM 决策</li>
<li>输出可能包含 <code>Thought</code>​ / <code>Action</code>​ / <code>Action Input</code>​ 等信息</li>
<li>对接前端时可能需要解析这些字段</li>
</ul></section><section><h3><strong>5. 异常处理</strong><a href="#5-异常处理"><span>#</span></a></h3><ul>
<li>工具执行可能失败 → Agent 要能处理异常</li>
<li>可以通过 <code>return_direct=True</code>​ 或 <code>callback</code>​ 捕获中间步骤</li>
</ul></section><section><h3><strong>6. 调试 &amp; 日志</strong><a href="#6-调试--日志"><span>#</span></a></h3><ul>
<li>​<code>verbose=True</code>​ 可以看到 Agent 内部思考过程</li>
<li>适合训练或调试复杂链路</li>
</ul></section><section><h3><strong>7. 性能 &amp; Token 消耗</strong><a href="#7-性能--token-消耗"><span>#</span></a></h3><ul>
<li>多工具、多步骤 → token 消耗大</li>
<li>可以缓存工具结果，或使用短 prompt</li>
<li>对接向量数据库等可做检索增强，减少重复调用 LLM</li>
</ul></section><section><h3><strong>8. 安全性</strong><a href="#8-安全性"><span>#</span></a></h3><ul>
<li>避免让 Agent 直接执行系统命令或删除文件等危险操作</li>
<li>如果必须，可加入 sandbox 或权限控制</li>
</ul><hr /></section></section>
<section><h2><strong>五、常见进阶用法</strong><a href="#五常见进阶用法"><span>#</span></a></h2><ol>
<li><strong>多工具 Agent</strong></li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>tools </span><span>=</span><span> [weather_tool, web_search_tool, sql_tool]</span></span></div></div><div><div><div>2</div></div><div><span><span>agent </span><span>=</span><span> </span><span>initialize_agent</span><span>(tools, llm, </span></span><span>agent</span><span>=</span><span>"zero-shot-react-description"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li><strong>带内存的对话 Agent</strong></li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> langchain.memory </span><span>import</span><span> ConversationBufferMemory</span></div></div><div><div><div>2</div></div><div><span><span>memory </span><span>=</span><span> </span><span>ConversationBufferMemory</span><span>(</span></span><span>memory_key</span><span>=</span><span>"chat_history"</span><span>)</span></div></div><div><div><div>3</div></div><div><span><span>agent </span><span>=</span><span> </span><span>initialize_agent</span><span>(tools, llm, </span></span><span>agent</span><span>=</span><span>"conversational-react-description"</span><span>, </span><span>memory</span><span><span>=</span><span>memory)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li><strong>Plan-and-Act Agent</strong></li>
</ol><ul>
<li>用于复杂任务，先生成步骤列表再逐步执行</li>
<li>适合自动化办公、数据分析、复杂决策任务</li>
</ul><hr /></section>
<section><h2><strong>六、总结</strong><a href="#六总结"><span>#</span></a></h2>

<table><thead><tr><th>核心概念</th><th>说明</th></tr></thead><tbody><tr><td>LLM</td><td>决策引擎</td></tr><tr><td>Tool</td><td>可执行操作接口</td></tr><tr><td>Agent 类型</td><td>决策策略（Zero-shot / ReAct / Conversational / Plan-and-Act）</td></tr><tr><td>Memory</td><td>对话或任务状态存储</td></tr><tr><td>Verbose</td><td>调试思考过程</td></tr><tr><td>Prompt</td><td>指导 LLM 选择工具和输出格式</td></tr></tbody></table><p>✅ <strong>最佳实践</strong></p><ul>
<li>工具描述清晰、函数幂等</li>
<li>ReAct 或 Plan-and-Act 优先</li>
<li>对话 Agent 配置 Memory</li>
<li>调试用 verbose</li>
<li>控制 token，注意安全</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://guoxin.wiki/posts/life-30000-days-product-exploration/</id>
      <title type="text">「人生 30000 天」产品方向探索：五轮否决之后剩下什么</title>
      <published>2026-07-27T00:00:00.000Z</published>
      <updated>2026-07-27T00:00:00.000Z</updated>
      <author><name>Guoxin</name></author>
      <link rel="alternate" href="https://guoxin.wiki/posts/life-30000-days-product-exploration/"/>
      <summary type="text">从一个「可视化人生倒计时」的点子出发，对竞品、差异化方向做了五轮探索和否决，记录下这个领域的真实困境和留给未来的四个切口。</summary>
      <content type="html"><![CDATA[<p><strong>原始想法：</strong> 做一个名为“人生30000天”的 App，核心功能是可视化展示“已活了多少天”和“还剩多少天”，并结合人生规划。</p>
<section><h2>二、现有竞品分析<a href="#二现有竞品分析"><span>#</span></a></h2><section><h3>2.1 竞品清单<a href="#21-竞品清单"><span>#</span></a></h3>

<table><thead><tr><th>应用名称</th><th>核心功能</th><th>特点与定位</th></tr></thead><tbody><tr><td><strong>30000days</strong></td><td>用 Emoji 记录心情、日记、待办，生成日历壁纸</td><td>轻量级日记和情绪追踪工具</td></tr><tr><td><strong>余生时钟</strong></td><td>记录生辰、年龄、人生进度，生日/纪念日提醒，桌面小组件</td><td>侧重记录重要之人的人生节点</td></tr><tr><td><strong>生命倒计时</strong></td><td>“生之时”记录已活天数，“死之钟”预测寿命并倒计时，有心愿单</td><td>死亡倒计时 + 心愿单，抖音曾火爆</td></tr><tr><td><strong>人生沙漏</strong></td><td>以“月”为单位的格子铺展人生，生命倒计时、里程碑、数据统计</td><td>视觉化表达直观，像“温柔的人生镜子”</td></tr><tr><td><strong>遗愿宝 (BucketPal)</strong></td><td>以“周”为单位的生命网格，将梦想按10个维度分类追踪</td><td>周数网格带来视觉冲击，结构化规划</td></tr><tr><td><strong>Lifedots</strong></td><td>点阵图可视化人生</td><td>极简视觉化</td></tr><tr><td><strong>Dayflower</strong></td><td>AI驱动极简日记，“一图一言”记录生活</td><td>自动整理成“生命之书”，构建“人生之树”</td></tr><tr><td><strong>魔力空间 (Mooly)</strong></td><td>AI个人成长助手，基于生命平衡轮八大维度追踪</td><td>AI生成日/周/月洞察复盘，数据可视化</td></tr><tr><td><strong>人生总结 – 生命时间线</strong></td><td>整个人生可视化时间追踪器</td><td>十年/年度视图网格，时间线事件气泡</td></tr><tr><td><strong>拾光记忆</strong></td><td>日记记录，热力图，人生时钟</td><td>一键导出PDF，情绪统计趋势</td></tr></tbody></table></section><section><h3>2.2 热度评估<a href="#22-热度评估"><span>#</span></a></h3>

<table><thead><tr><th>热度级别</th><th>代表产品</th><th>表现</th></tr></thead><tbody><tr><td><strong>现象级爆款</strong></td><td>“死了么”App</td><td>登顶 App Store 付费榜首，估值千万，三天日下载量突破50万</td></tr><tr><td><strong>社交平台爆火</strong></td><td>“生命倒计时”</td><td>抖音上被大量做成锁屏壁纸，短视频病毒式传播</td></tr><tr><td><strong>持续运营/小众</strong></td><td>遗愿宝、人生沙漏、Dayflower</td><td>有固定用户群，能维持运营，但非全网刷屏级别</td></tr></tbody></table><p><strong>核心结论：</strong> 概念本身被验证过，爆款出圈靠的是“情绪钩子”+“社交货币”，而非功能复杂程度。</p></section></section>
<section><h2>三、探索过的差异化方向（及被否决原因）<a href="#三探索过的差异化方向及被否决原因"><span>#</span></a></h2><section><h3>3.1 第一阶段：功能层面的差异化<a href="#31-第一阶段功能层面的差异化"><span>#</span></a></h3>

<table><thead><tr><th>方向</th><th>说明</th><th>被否决原因</th></tr></thead><tbody><tr><td>“正计时”代替“倒计时”</td><td>展示“已认真活过的天数”，强调积累感</td><td>仍是同一框架下的变体，用户心智变化不大</td></tr><tr><td>关系视角</td><td>“我们还剩多少天一起过”，连接父母/伴侣</td><td>有价值，但仍是“倒计时”的情感变体</td></tr><tr><td>生命宽度</td><td>量化体验丰富度，做“人生体验清单”</td><td>本质还是“规划”工具，门槛高</td></tr></tbody></table></section><section><h3>3.2 第二阶段：AI大模型整合方向<a href="#32-第二阶段ai大模型整合方向"><span>#</span></a></h3>

<table><thead><tr><th>方向</th><th>说明</th><th>被否决原因</th></tr></thead><tbody><tr><td>AI人生复盘</td><td>AI分析日记/相册/位置，生成洞察报告</td><td>与大模型直接对话相比，无准确性优势</td></tr><tr><td>大模型上层应用</td><td>调用API，将建议放入时间容器持续追踪</td><td>用户自己问大模型更直接；连记账App都难存活</td></tr></tbody></table><p><strong>核心问题：</strong> 大模型记账类应用尚且面临用户新鲜感一过就流失的困境，人生规划类输入成本更高、反馈周期更长，更难存活。</p></section><section><h3>3.3 第三阶段：零输入方向<a href="#33-第三阶段零输入方向"><span>#</span></a></h3>

<table><thead><tr><th>方向</th><th>说明</th><th>被否决原因</th></tr></thead><tbody><tr><td>自动读取健康/相册/日历数据</td><td>用户无需输入，自动呈现人生数据画像</td><td>已有产品在做（如 Apple Health 聚合、相册回忆）</td></tr><tr><td>隐私即卖点</td><td>本地处理数据，不上传云端</td><td>隐私是功能属性，不足以成为独立卖点</td></tr></tbody></table></section><section><h3>3.4 第四阶段：纯软件售卖方向<a href="#34-第四阶段纯软件售卖方向"><span>#</span></a></h3>

<table><thead><tr><th>方向</th><th>说明</th><th>被否决原因</th></tr></thead><tbody><tr><td>人生说明书（一次性买断）</td><td>读取本地数据，自动生成PDF报告，用户买断即用</td><td>竞品已存在（Dayflower、人生总结、拾光记忆等均支持报告导出）</td></tr></tbody></table></section><section><h3>3.5 第五阶段：AI回忆录/家族记忆方向<a href="#35-第五阶段ai回忆录家族记忆方向"><span>#</span></a></h3>

<table><thead><tr><th>方向</th><th>说明</th><th>被否决原因</th></tr></thead><tbody><tr><td>AI回忆录生成</td><td>帮老人/个人生成回忆录</td><td>已有公司入局（慰康智能、清诺谛听、小鹿光年）</td></tr><tr><td>家族记忆传承</td><td>家族私密空间，AI整合故事和影像</td><td>使用门槛极高，需全家参与输入</td></tr></tbody></table></section></section>
<section><h2>四、多轮探索后的核心发现<a href="#四多轮探索后的核心发现"><span>#</span></a></h2><section><h3>4.1 这个领域的本质困境<a href="#41-这个领域的本质困境"><span>#</span></a></h3><ol>
<li><strong>概念被反复验证，也意味着被反复挖掘</strong> —— “人生30000天”框架下的各种变体几乎都有人尝试过</li>
<li><strong>输入门槛 vs 获得价值 的鸿沟</strong> —— 用户必须“先干活才能获得价值”，绝大多数人在这一步流失</li>
<li><strong>大模型不是护城河</strong> —— 用户可以直接向大模型提问，且回答质量可能更高</li>
<li><strong>竞品已覆盖主流方向</strong> —— 记录、规划、倒计时、报告生成、AI复盘……均有成熟产品</li>
</ol></section><section><h3>4.2 创业者面临的现实约束（来自用户明确表达）<a href="#42-创业者面临的现实约束来自用户明确表达"><span>#</span></a></h3><ul>
<li>❌ 不做需要持续运营的 App</li>
<li>❌ 不接入大模型（避免 API 成本和依赖）</li>
<li>✅ 想做纯软件售卖（一次性买断）</li>
<li>✅ 想找到“互联网上完全没有”的方向</li>
</ul></section><section><h3>4.3 核心矛盾<a href="#43-核心矛盾"><span>#</span></a></h3><blockquote><p><strong>“蓝海方向”往往需要教育用户 → 教育用户需要资本和运营</strong>
<strong>“红海方向”竞争激烈 → 纯软件卖断难以突围</strong></p></blockquote><p>两者之间存在天然张力。</p></section></section>
<section><h2>五、留给未来的可能思考方向<a href="#五留给未来的可能思考方向"><span>#</span></a></h2><p>如果在当前约束条件下暂时未找到合适方向，以下是一些可以继续关注/探索的视角：</p><ol>
<li><strong>垂直人群</strong> —— 能否不为“所有人”做产品，而是聚焦某类极细分人群（如高考前100天倒计时、新人入职100天）？</li>
<li><strong>实体化/礼品化</strong> —— 能否将软件生成的报告做成实体书/礼盒，走礼品经济路线（如“给父母的礼物”）？</li>
<li><strong>工具化/插件化</strong> —— 能否不做一个独立 App，而是一个 Excel/Notion 模板、或手机小组件合集？</li>
<li><strong>等待新平台/新硬件</strong> —— 是否可以在 Vision Pro / 智能戒指 / 智能相框等新载体上寻找机会？</li>
</ol></section>
<section><h2>六、文档信息<a href="#六文档信息"><span>#</span></a></h2><ul>
<li><strong>生成日期：</strong> 2026-07-27</li>
<li><strong>对话轮次：</strong> 多轮探索与排除</li>
<li><strong>当前状态：</strong> 已排除多个主流方向，未找到符合“蓝海 + 纯软件售卖”双重约束的明确切入点</li>
<li><strong>建议后续动作：</strong> 可根据自身资源/能力，重新评估约束条件（如是否接受轻度运营、是否接受非独立 App 形态），或在垂直细分领域进行更深入的定性调研</li>
</ul><hr /><p><em>“有时，排除掉所有可能性后，剩下的那个——哪怕再难——就是答案。”</em></p></section>]]></content>
    </entry>
</feed>
