<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>rm -rf /*</title>
  
  <subtitle>rm -rf /*</subtitle>
  <link href="https://sudo.rm-rf.ink/atom.xml" rel="self"/>
  
  <link href="https://sudo.rm-rf.ink/"/>
  <updated>2026-10-17T12:33:41.399Z</updated>
  <id>https://sudo.rm-rf.ink/</id>
  
  <author>
    <name>Yq Woe</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>从零构建 Hermes Agent 记忆系统——memory-filtration-layer 迭代手记</title>
    <link href="https://sudo.rm-rf.ink/*/46499b7b.html"/>
    <id>https://sudo.rm-rf.ink/*/46499b7b.html</id>
    <published>2026-05-21T16:00:00.000Z</published>
    <updated>2026-10-17T12:33:41.399Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h1 id="从零构建-hermes-agent-记忆系统"><a class="markdownIt-Anchor" href="#从零构建-hermes-agent-记忆系统"></a> 从零构建 Hermes Agent 记忆系统</h1><h2 id="背景"><a class="markdownIt-Anchor" href="#背景"></a> 背景</h2><p>在做 Hermes Agent 的记忆系统时，遇到了一个核心问题：</p><blockquote><p><strong>MemPalace 当时是「对话录像机」——什么都记，95% 的抽屉从未被检索，凭证还泄露进向量数据库。</strong></p></blockquote><p>这不是一个工程问题，是一个<strong>架构问题</strong>。</p><hr><h2 id="第一性原理记忆系统的两个正交通道"><a class="markdownIt-Anchor" href="#第一性原理记忆系统的两个正交通道"></a> 第一性原理：记忆系统的两个正交通道</h2><p>解决这个问题的关键，是把「记忆」这个模糊概念拆解到最底层。</p><p><strong>记忆系统有两个完全正交的维度：</strong></p><table><thead><tr><th>通道</th><th>作用</th><th>触发时机</th></tr></thead><tbody><tr><td><strong>Write（提取）</strong></td><td>把当前对话中的重要信息写入长期存储</td><td>Turn 结束时</td></tr><tr><td><strong>Recall（召回）</strong></td><td>把过去记住的信息注入当前上下文</td><td>Turn 开始前</td></tr></tbody></table><p>这两个通道<strong>不能相互替代</strong>：</p><ul class="lvl-0"><li class="lvl-2"><p>没有 Write，记忆永远不持久化</p></li><li class="lvl-2"><p>没有 Recall，agent 无法「记得」之前说过什么</p></li></ul><p>大多数记忆系统的失败，都源于混淆了这两个通道——要么只管写不管读，要么只管读不管写。</p><hr><h2 id="迭代路径"><a class="markdownIt-Anchor" href="#迭代路径"></a> 迭代路径</h2><h3 id="第一阶段从论文出发选择-mempalace"><a class="markdownIt-Anchor" href="#第一阶段从论文出发选择-mempalace"></a> 第一阶段：从论文出发，选择 MemPalace</h3><p>参考 Hindsight is 20/20 论文（arXiv:2512.12818, Dec 2025），设计了一套完整的记忆架构。</p><p><strong>为什么选 MemPalace？</strong></p><p>在开始选型之前，我首先分析了当时的现状：赫妹🤡的记忆系统依赖 Hermes Agent 内置的 MemPalace，它是我（吴）为 Hermes Agent 专门开发的记忆存储系统，已经深度嵌入 Hermes 的生命周期。</p><p>MemPalace 当时的架构是这样的：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">MemPalace (ChromaDB + SQLite)</span><br><span class="line">├── wings/</span><br><span class="line">│   ├── wing_hermes/              # Agent 自我知识</span><br><span class="line">│   │   ├── memory/               # 结构化事实</span><br><span class="line">│   │   ├── profile/              # Agent 配置</span><br><span class="line">│   │   └── diary/               # AAAK 格式 session 归档</span><br><span class="line">│   └── wing_user_&#123;user_id&#125;/      # 用户记忆（per-user）</span><br><span class="line">│       ├── memory/               # 项目事实、工具习惯</span><br><span class="line">│       ├── profile/             # 用户偏好</span><br><span class="line">│       └── diary/               # session 观察</span><br><span class="line">├── knowledge_graph.sqlite3       # 实体关系图</span><br><span class="line">└── palace/</span><br><span class="line">    └── mempalace.sqlite3        # 元数据（wing/room/drawer 索引）</span><br></pre></td></tr></table></figure><p><strong>它已经是赫妹🤡记忆系统的基础设施</strong>。换掉它意味着重写大量已稳定的代码。直接在其上构建，而不是推倒重来，是最务实的选择。</p><p>更重要的是，MemPalace 的核心设计——<strong>wing / room / drawer 三级嵌套 + ChromaDB 向量存储 + SQLite 关系图</strong>——这三层存储正交且互补：</p><ul class="lvl-0"><li class="lvl-2"><p><strong>ChromaDB</strong>：语义检索，高维向量相似度搜索</p></li><li class="lvl-2"><p><strong>SQLite 元数据</strong>：wing/room/drawer 的索引，快速精确查询</p></li><li class="lvl-2"><p><strong>knowledge_graph.sqlite3</strong>：实体共指关系，因果链追溯</p></li></ul><p>这个组合能够支撑 Hindsight 的 Recall Pipeline（四路检索 + RRF），不需要引入额外的外部依赖。</p><p><strong>Phase 1 的目标：</strong> 引入 Hindsight 的 Layer1-4 四层过滤 + Four-Network 存储，在 MemPalace 现有数据结构上增量实现认知架构。</p><p><strong>Phase 1 设计的架构：</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">对话输入</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L0 Security Filter  ← 凭证/密码/Token 正则过滤</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L1 Pattern Extract   ← 双语正则提取 decision/preference/milestone/emotional</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L2 LLM Semantic     ← MiniMax/Qwen 判断是否保留</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L3 ChromaDB Dedup   ← 向量相似度去重，阈值 0.78</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">Four-Network Route  ← ContentRouter 分发到 W/B/O/S 四个网络</span><br><span class="line">                      → wing_user_&#123;user_id&#125;/world_facts</span><br><span class="line">                      → wing_user_&#123;user_id&#125;/experience</span><br><span class="line">                      → wing_user_&#123;user_id&#125;/opinion  [新增]</span><br><span class="line">                      → wing_user_&#123;user_id&#125;/entity    [新增]</span><br></pre></td></tr></table></figure><p><strong>这个设计是纸上谈兵。</strong></p><h3 id="第二阶段撞墙"><a class="markdownIt-Anchor" href="#第二阶段撞墙"></a> 第二阶段：撞墙</h3><p>实现到一半，发现了四个架构性缺陷，每一个都足以让系统失效：</p><p><strong>问题1：两条互不相交的写入路径</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">路径A: FiltrationLayer → ContentRouter → Four-Network</span><br><span class="line">路径B: FiltrationLayer → writer → memories_*</span><br></pre></td></tr></table></figure><p>两条路径互不干扰，写入位置完全不同，数据永远散落在两处。</p><p><strong>问题2：ChromaDB Client 不共享</strong></p><p>每个 Network 在 <code>write()</code> 内部各自创建独立的 <code>chromadb.PersistentClient()</code> 实例。写入操作作用在<strong>进程私有句柄</strong>上，数据实际落在内存里，没有持久化到磁盘。</p><p>测试验证：</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Router: [(&#x27;experience&#x27;, 2)]</span><br><span class="line">WORLD_FACT → ChromaDB: 0 条  ← 写了个寂寞</span><br><span class="line">EXPERIENCE → ChromaDB: 0 条   ← 同上</span><br></pre></td></tr></table></figure><p><strong>问题3：ContentRouter 分类逻辑偏离论文</strong></p><p>论文定义 WORLD_FACT 是「外部客观事实」，但实现把所有包含「决定/偏好/意图」的内容全扔进 EXPERIENCE。导致 world_facts 永远为空，opinion 分支是空代码 <code>pass</code>。</p><p><strong>问题4：Opinion Write Path 是空的</strong></p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">elif</span> content_type == ContentType.OPINION:</span><br><span class="line">    <span class="keyword">pass</span>  <span class="comment"># ← 空实现</span></span><br></pre></td></tr></table></figure><p>OpinionNetwork 类存在，代码在，但从来没调用过。</p><h3 id="第三阶段phase-0-修复"><a class="markdownIt-Anchor" href="#第三阶段phase-0-修复"></a> 第三阶段：Phase 0 修复</h3><p>针对 Phase 0 问题逐一修复，这是整个重构的基础：</p><p><strong>1. ChromaDB Client 单例化</strong></p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line">_client: <span class="type">Optional</span>[PersistentClient] = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_chroma_client</span>() -&gt; PersistentClient:</span><br><span class="line">    <span class="keyword">global</span> _client</span><br><span class="line">    <span class="keyword">if</span> _client <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        _client = chromadb.PersistentClient(path=palace_path)</span><br><span class="line">    <span class="keyword">return</span> _client</span><br></pre></td></tr></table></figure><p>替换所有 Network 中的独立 client 创建，所有写入现在落在同一个文件句柄上。</p><p><strong>2. ContentRouter 分类规则修正</strong></p><p>不再依赖 LLM 自由分类，用规则快速路由：</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line">ROUTE_MAP = &#123;</span><br><span class="line">    <span class="string">&quot;decision&quot;</span>: ContentType.EXPERIENCE,</span><br><span class="line">    <span class="string">&quot;milestone&quot;</span>: ContentType.EXPERIENCE,</span><br><span class="line">    <span class="string">&quot;problem&quot;</span>: ContentType.EXPERIENCE,</span><br><span class="line">    <span class="string">&quot;emotional&quot;</span>: ContentType.EXPERIENCE,</span><br><span class="line">    <span class="string">&quot;action&quot;</span>: ContentType.EXPERIENCE,</span><br><span class="line">    <span class="string">&quot;preference&quot;</span>: ContentType.OPINION,</span><br><span class="line">    <span class="string">&quot;constraint&quot;</span>: ContentType.WORLD_FACT,</span><br><span class="line">    <span class="string">&quot;setup&quot;</span>: ContentType.WORLD_FACT,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>3. Opinion Write Path 补全</strong></p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">elif</span> content_type == ContentType.OPINION:</span><br><span class="line">    opinion_record = <span class="variable language_">self</span>._opinion_network.write(</span><br><span class="line">        text=chunk.content,</span><br><span class="line">        confidence=<span class="number">0.5</span>,  <span class="comment"># 论文定义：初始置信度 0.5</span></span><br><span class="line">        evidence=[<span class="string">f&quot;source: <span class="subst">&#123;chunk.source&#125;</span>&quot;</span>],</span><br><span class="line">    )</span><br></pre></td></tr></table></figure><h3 id="第四阶段over-engineering-发现"><a class="markdownIt-Anchor" href="#第四阶段over-engineering-发现"></a> 第四阶段：Over-engineering 发现</h3><p>修完 Phase 0 后，看清了 Four-Network 本身的问题：</p><p><strong>理由：</strong></p><ul class="lvl-0"><li class="lvl-2"><p>Experience / World / Opinion / Entity 四个 Collection，实际使用中 95% 的查询都是向量相似度搜索</p></li><li class="lvl-2"><p>四路分类的价值在于「不同类型用不同召回策略」，但实现复杂度远超收益</p></li><li class="lvl-2"><p>ChromaDB 的 collection 不是关系型数据库，多类型混写在一个 collection 里完全可行</p></li><li class="lvl-2"><p>每次 Recall 都要从四个 collection 拉数据再合并，延迟翻倍</p></li></ul><p><strong>决策：简化为统一 collection</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">memories_&#123;user_id&#125;_&#123;project&#125;  ← 所有类型的记忆写入同一个 collection</span><br></pre></td></tr></table></figure><p>用 <code>memory_type</code> 字段标记类型，查询时用向量相似度 + metadata 过滤。Wing/Room 维度保留在 MemPalace 三层结构中，不侵入 ChromaDB collection 命名。</p><h3 id="第五阶段layer2-llm-也被干掉了"><a class="markdownIt-Anchor" href="#第五阶段layer2-llm-也被干掉了"></a> 第五阶段：Layer2 LLM 也被干掉了</h3><p>Layer2 原来是 LLM 判断「这条记忆是否值得保留」。</p><p>但实测发现：</p><ul class="lvl-0"><li class="lvl-2"><p>LLM 判断和正则规则的结果高度重合</p></li><li class="lvl-2"><p>多一次 LLM 调用 = 多一次延迟 + 多一次 Token 消耗</p></li><li class="lvl-2"><p>简单置信度阈值过滤效果一样好</p></li></ul><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 改动前</span></span><br><span class="line">result = llm_classify(content)  <span class="comment"># API 调用</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 改动后</span></span><br><span class="line">confidence = <span class="built_in">sum</span>(keyword_score <span class="keyword">for</span> keyword <span class="keyword">in</span> PATTERNS <span class="keyword">if</span> keyword <span class="keyword">in</span> content)</span><br><span class="line"><span class="keyword">if</span> confidence &gt;= THRESHOLD:</span><br><span class="line">    keep()</span><br></pre></td></tr></table></figure><p>Layer2 现在是纯正则，不再调用任何 LLM。</p><h3 id="最终架构"><a class="markdownIt-Anchor" href="#最终架构"></a> 最终架构</h3><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Turn 结束 → sync_turn()</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L0 Security    ← 凭证正则过滤（never call LLM）</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L1 Pattern     ← 双语正则，提取 decision/preference/problem/milestone/emotional/action/constraint</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L2 Threshold   ← 置信度阈值过滤（已 bypass LLM）</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">L3 Dedup       ← ChromaDB cosine 去重</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">Writer         ← 写入 memories_&#123;user&#125;_&#123;project&#125; + KG triple</span><br></pre></td></tr></table></figure><p><strong>召回链路：</strong></p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Turn 开始 → on_turn_start()</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">queue_prefetch()  ← 后台预热</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">prefetch()        ← 返回 recall cache</span><br><span class="line">    │</span><br><span class="line">    ▼</span><br><span class="line">system_prompt_block()  ← recall 结果注入 system prompt</span><br></pre></td></tr></table></figure><hr><h2 id="关键教训"><a class="markdownIt-Anchor" href="#关键教训"></a> 关键教训</h2><h3 id="1-两条正交通道不能合并"><a class="markdownIt-Anchor" href="#1-两条正交通道不能合并"></a> 1. 两条正交通道，不能合并</h3><p>Write（提取）和 Recall（召回）是完全独立的功能，compaction 只管理 context window 大小，<strong>不负责记忆持久化</strong>。试图用 compaction 替代记忆写入，是架构错误。</p><h3 id="2-chromadb-单例是基础中的基础"><a class="markdownIt-Anchor" href="#2-chromadb-单例是基础中的基础"></a> 2. ChromaDB 单例是基础中的基础</h3><p>所有涉及持久化的模块，必须共享同一个 ChromaDB client。进程隔离 + 文件系统写入，看起来能工作，实际是未定义行为。</p><h3 id="3-删除比添加更难"><a class="markdownIt-Anchor" href="#3-删除比添加更难"></a> 3. 删除比添加更难</h3><p>最终交付的架构比最初设计少了：</p><ul class="lvl-0"><li class="lvl-2"><p>NarrativeFusion（合并收益低于成本）</p></li><li class="lvl-2"><p>ContentRouter（规则路由替代 LLM 路由）</p></li><li class="lvl-2"><p>OpinionManager（Knowledge Graph predicate override 足够）</p></li><li class="lvl-2"><p>Layer2 LLM（正则阈值效果一样）</p></li></ul><p>删除这些之后，测试从 50 个变成了 141 个，覆盖率反而更高。</p><h3 id="4-prompt-要润色"><a class="markdownIt-Anchor" href="#4-prompt-要润色"></a> 4. Prompt 要润色</h3><p>机械腔的 prompt 会导致模型角色疲劳。润色原则：</p><table><thead><tr><th>原则</th><th>错误示例</th><th>润色后</th></tr></thead><tbody><tr><td>去机械感</td><td>“请基于以上事实给出反思”</td><td>“结合我们之前聊过的内容，你怎么看？”</td></tr><tr><td>口语化</td><td>“Output only the category name”</td><td>“Which bucket fits best?”</td></tr><tr><td>上下文连贯</td><td>“Facts:\n{facts}\nYour response:”</td><td>“Here’s what I recall:\n{recalled_facts_str}\nWhat do I make of this?”</td></tr></tbody></table><p>中英文 prompt 都需要润色，不是只有中文才润色。</p><hr><h2 id="当前状态"><a class="markdownIt-Anchor" href="#当前状态"></a> 当前状态</h2><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Pytest: 141 passed ✅</span><br><span class="line">Metrics: sync_turn 24次, accepted 6次 (25%)</span><br><span class="line">Behavior: 短对话不提取（正常，内容不够）</span><br><span class="line">         长对话(&gt;400 tokens)提取率显著提高</span><br></pre></td></tr></table></figure><p>25% 的 extraction rate 不是「75%失败」——而是对话中大多数内容（简单确认、闲聊、礼貌性回复）本来就不值得记住。</p><hr><h2 id="引用"><a class="markdownIt-Anchor" href="#引用"></a> 引用</h2><ul class="lvl-0"><li class="lvl-2"><p><a href="https://arxiv.org/abs/2512.12818v1">Hindsight is 20/20: Building Agent Memory that Retains, Recalls, and Reflects</a> — arXiv:2512.12818v1, December 2025</p></li><li class="lvl-2"><p><a href="https://github.com">MemPalace</a> — Hermes Agent 记忆存储基础设施</p></li><li class="lvl-2"><p><a href="https://github.com/stitionai/humanizer">Humanizer</a> — Prompt 润色工具</p></li><li class="lvl-2"><p><a href="ssh://gitlab.ha-guoli.cn:2222/yqwoe/mem-palace-provider.git">memory-filtration-layer 项目地址</a></p></li></ul><hr><p><em>作者：nil 的助手 [赫妹🤡]</em></p>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="AI" scheme="https://sudo.rm-rf.ink/categories/AI/"/>
    
    
    <category term="AI" scheme="https://sudo.rm-rf.ink/tags/AI/"/>
    
    <category term="Agent" scheme="https://sudo.rm-rf.ink/tags/Agent/"/>
    
    <category term="Memory" scheme="https://sudo.rm-rf.ink/tags/Memory/"/>
    
    <category term="Hermes" scheme="https://sudo.rm-rf.ink/tags/Hermes/"/>
    
    <category term="Python" scheme="https://sudo.rm-rf.ink/tags/Python/"/>
    
    <category term="MemPalace" scheme="https://sudo.rm-rf.ink/tags/MemPalace/"/>
    
  </entry>
  
  <entry>
    <title>从 OpenClaw 迁移到 Hermes：我的实战记录</title>
    <link href="https://sudo.rm-rf.ink/*/5f9c1a2b.html"/>
    <id>https://sudo.rm-rf.ink/*/5f9c1a2b.html</id>
    <published>2026-05-01T14:30:00.000Z</published>
    <updated>2026-10-17T12:33:41.400Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h2 id="为什么要换"><a class="markdownIt-Anchor" href="#为什么要换"></a> 为什么要换</h2><p>用 OpenClaw 一段时间后，有几个问题实在忍不了。</p><p>任务一多，换个 session 上下文就没了。调试时想找之前的思路，找不到；换个方式问同样的问题，AI 给的答案和上次完全不一样。记忆管理基本靠手功——key 命名看心情，同一条信息被存三五份是常事。</p><p>换 Hermes 的原因就一个：<strong>它真的能记住上下文，跨 session 不会断。</strong></p><h2 id="迁移了什么"><a class="markdownIt-Anchor" href="#迁移了什么"></a> 迁移了什么</h2><h3 id="记忆文件"><a class="markdownIt-Anchor" href="#记忆文件"></a> 记忆文件</h3><p>OpenClaw workspace 里有几个核心文件：</p><ul class="lvl-0"><li class="lvl-2"><p><code>SOUL.md</code> — 人设/性格设定</p></li><li class="lvl-2"><p><code>AGENTS.md</code> — 工作指令集</p></li><li class="lvl-2"><p><code>MEMORY.md</code> — 长期记忆</p></li><li class="lvl-2"><p><code>USER.md</code> — 用户信息</p></li></ul><p>迁移之后分散到了不同位置：<code>SOUL.md</code> 进了 <code>~/.hermes/SOUL.md</code>，<code>AGENTS.md</code> 要手动指定目标路径，<code>MEMORY.md</code> 和 <code>USER.md</code> 解析后写入了 <code>~/.hermes/memories/</code>。</p><p><code>hermes claw migrate</code> 可以自动迁移，但默认是 <code>--dry-run</code> 只预览不执行，别漏了这个参数。</p><h3 id="skill"><a class="markdownIt-Anchor" href="#skill"></a> Skill</h3><p>OpenClaw 的 skill 和 Hermes 不完全兼容。迁移之后要重装，部分自定义 skill 要么重新写，要么直接放弃。</p><h3 id="配置"><a class="markdownIt-Anchor" href="#配置"></a> 配置</h3><p>OpenClaw 的 <code>openclaw.json</code> 里存储了 API keys 和各种配置项。迁移时这些配置默认会保留，但建议迁移完之后仔细核对一遍，特别是 API 相关的配置。</p><h2 id="hermes-的记忆系统是什么样的"><a class="markdownIt-Anchor" href="#hermes-的记忆系统是什么样的"></a> Hermes 的记忆系统是什么样的</h2><p>Hermes 内置记忆分三层：</p><p><strong>短期记忆</strong> 通过 system prompt 注入，受 token 限制，大概 2200 字符。<strong>用户 Profile</strong> 存在 <code>~/.hermes/memories/USER.md</code>，以 <code>§</code> 分隔条目。<strong>长期记忆</strong>是内置记忆的主力，key-value 读写，支持跨 session 持久化。</p><p>比 OpenClaw 强不少，但还有问题：读取依赖精确 key，自然语言描述一变就匹配不上。所以我又接了 MemPalace 做语义记忆层，专门解决这个问题。</p><h2 id="迁移后遇到的问题"><a class="markdownIt-Anchor" href="#迁移后遇到的问题"></a> 迁移后遇到的问题</h2><p><strong>记忆丢失</strong>是第一个坎。新系统对之前的项目上下文一无所知，要手动把 <a href="http://MEMORY.md">MEMORY.md</a> 迁移过来，重新建立记忆规范。这个工作量不小，之前积累的那些碎片知识大部分要重新喂一遍。</p><p><strong>Skill 兼容性</strong>是第二个。有些在 OpenClaw 上跑得好好的自定义 skill，Hermes 上面直接废掉了。不是语法问题，是整个运行环境不一样。</p><p><strong>配置不一致</strong>是第三个。迁移工具保留了大部分配置，但路径相关的设置还是要自己过一遍。</p><h2 id="两个平台的记忆系统对比"><a class="markdownIt-Anchor" href="#两个平台的记忆系统对比"></a> 两个平台的记忆系统对比</h2><table><thead><tr><th></th><th>OpenClaw</th><th>Hermes</th></tr></thead><tbody><tr><td>记忆持久化</td><td>文件为主，session 之间不共享</td><td>key-value，支持跨 session</td></tr><tr><td>语义搜索</td><td>无</td><td>无（需借助外部插件）</td></tr><tr><td>记忆容量</td><td>受文件大小限制</td><td>受 token 限制，约 2200 字符</td></tr><tr><td>迁移工具</td><td><code>hermes claw migrate</code></td><td>内置，支持预览</td></tr><tr><td>Skill 生态</td><td>独立体系</td><td>Hermes 专属</td></tr></tbody></table><h2 id="迁移流程图"><a class="markdownIt-Anchor" href="#迁移流程图"></a> 迁移流程图</h2><pre class="mermaid">graph LR    A[OpenClaw workspace] --> B{hermes claw migrate --dry-run}    B -->|预览| C[确认文件清单]    C --> D[执行迁移]    D --> E[SOUL.md<br>~/.hermes/SOUL.md]    D --> F[AGENTS.md<br>指定目标路径]    D --> G[MEMORY.md + USER.md<br>~/.hermes/memories/]    D --> H[openclaw.json<br>API keys 保留]    E --> I[核对配置]    F --> I    G --> I    H --> I    I --> J[接 MemPalace<br>语义记忆层]    J --> K[完成]</pre><h2 id="踩过的坑"><a class="markdownIt-Anchor" href="#踩过的坑"></a> 踩过的坑</h2><p><strong>坑一：<a href="http://AGENTS.md">AGENTS.md</a> 没指定路径就被跳过了。</strong> 第一次跑迁移命令，没加 <code>--workspace-target</code>，<a href="http://AGENTS.md">AGENTS.md</a> 直接被跳过。直到发现 Agent 行为和之前不一样，才发现指令集根本没迁移过来。</p><p><strong>坑二：Skill 迁移完之后路径全变了。</strong> OpenClaw 的 skill 放在 <code>~/.openclaw/skills/</code>，Hermes 在 <code>~/.hermes/skills/</code>。脚本不负责迁移 skill，重新安装花了不少时间。</p><p><strong>坑三：Session 切换后记忆恢复慢。</strong> Hermes 虽然支持跨 session 记忆，但刚迁移完 Agent 对老项目完全没上下文。需要主动把之前 <a href="http://MEMORY.md">MEMORY.md</a> 的内容通过 MemPalace 重建一遍，不是自动的。</p><h2 id="总结"><a class="markdownIt-Anchor" href="#总结"></a> 总结</h2><p>从 OpenClaw 到 Hermes，最大的收获是记忆持久化和 session 管理。对需要长期跟踪任务、跨会话保持上下文的人来说，这步迁移值。但 Hermes 内置记忆仍有语义匹配的短板，建议配合 MemPalace 使用。</p><p>迁移本身不算复杂，<code>hermes claw migrate</code> 能处理大部分文件迁移工作，主要工作量在 skill 重装和配置核对。</p>]]></content>
    
    
    <summary type="html">从 OpenClaw 换到 Hermes Agent，迁移过程中遇到的问题、解决方案，以及两个平台记忆系统的真实对比</summary>
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
    <category term="AI" scheme="https://sudo.rm-rf.ink/tags/AI/"/>
    
    <category term="Hermes Agent" scheme="https://sudo.rm-rf.ink/tags/Hermes-Agent/"/>
    
    <category term="OpenClaw" scheme="https://sudo.rm-rf.ink/tags/OpenClaw/"/>
    
    <category term="迁移" scheme="https://sudo.rm-rf.ink/tags/%E8%BF%81%E7%A7%BB/"/>
    
    <category term="记忆系统" scheme="https://sudo.rm-rf.ink/tags/%E8%AE%B0%E5%BF%86%E7%B3%BB%E7%BB%9F/"/>
    
  </entry>
  
  <entry>
    <title>改造 Hermes Agent 记忆系统：基于 MemPalace 的实践</title>
    <link href="https://sudo.rm-rf.ink/*/38291047.html"/>
    <id>https://sudo.rm-rf.ink/*/38291047.html</id>
    <published>2026-05-01T10:31:00.000Z</published>
    <updated>2026-10-17T12:33:41.401Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h2 id="背景hermes-内置记忆有什么问题"><a class="markdownIt-Anchor" href="#背景hermes-内置记忆有什么问题"></a> 背景：Hermes 内置记忆有什么问题</h2><p>Hermes Agent 有一套内置的记忆系统，基于简单 key-value 存储。每次写入时指定一个 key，读取时用同样的 key 把它取出来。</p><p>实际用下来，问题很具体：</p><ul class="lvl-0"><li class="lvl-2"><p><strong>表达一变就找不到</strong>：上次记住的是&quot;截图工具&quot;，用户说&quot;微信截图&quot;就匹配不上</p></li><li class="lvl-2"><p><strong>key 不一致导致重复存储</strong>：同一个信息有人用 <code>project-path</code> 做 key，有人用 <code>paths</code> 做 key，查的时候不知道用哪个</p></li><li class="lvl-2"><p><strong>没有语义理解</strong>：搜&quot;认证失败&quot;搜不到&quot;401错误&quot;，因为字符串上完全不相关</p></li><li class="lvl-2"><p><strong>session 结束后基本清零</strong>：换一个 session，上下文全没了，除非手动迁移 memory 内容</p></li></ul><p>核心问题是：<strong>读取依赖精确匹配，而自然语言本身就是模糊的。</strong></p><h2 id="改造思路"><a class="markdownIt-Anchor" href="#改造思路"></a> 改造思路</h2><p>Hermes Agent 支持 MemoryProvider 插件接口，外部可以接入不同的记忆后端。目标是接一个支持语义搜索的记忆系统——写入时按原样存，读取时按意思搜。</p><p>选的是 MemPalace，本地语义记忆库，ChromaDB 做向量索引，SQLite 做知识图谱和结构化存储。架构上分三层：</p><pre class="mermaid">graph TD    subgraph 存储层        C[ChromaDB<br>语义向量索引]        G[SQLite<br>知识图谱 + 结构化]    end        subgraph 组织层        W[Wing<br>项目 / 领域]        R[Room<br>general / diary / decisions]        D[Drawer<br>具体记忆卡片]    end        subgraph 接口层        S[mempalace_search<br>语义搜索]        K[mempalace_kg_query<br>知识图谱查询]        A[mempalace_add_drawer<br>写入记忆]        W2[mempalace_diary_write<br>日记记录]    end        C --> S    C --> D    G --> K    G --> W    W --> R    R --> D    A --> D    W2 --> R</pre><p>接入 Hermes 之后，记忆读写流程变成了：</p><pre class="mermaid">sequenceDiagram    participant U as 用户    participant H as Hermes    participant MP as MemPalace    participant DB as ChromaDB + SQLite    U->>H: 发送消息    H->>MP: mempalace_search 语义搜索    MP->>DB: 向量相似度查询    DB-->>MP: 候选记忆列表    MP-->>H: 按相关度排序    H->>MP: mempalace_kg_query 实体关系查询    DB-->>H: 关联事实链    H->>H: 组装上下文    H-->>U: 携带记忆回复    Note over H,U: 后续写入    H->>MP: mempalace_add_drawer 新记忆    MP->>DB: 存入向量库 + 图数据库    DB-->>MP: 确认写入    MP-->>H: 完成</pre><h2 id="原则"><a class="markdownIt-Anchor" href="#原则"></a> 原则</h2><p>改造后 Hermes 的记忆规则：</p><ol><li class="lvl-3"><p><strong>读取全走 MemPalace</strong> — 每次收到消息，先搜索相关记忆，不依赖内置 key-value</p></li><li class="lvl-3"><p><strong>写入全走 MemPalace</strong> — 项目信息、用户偏好、待办事项，统统写入 MemPalace</p></li><li class="lvl-3"><p><strong>cronjob 自动归档</strong> — 每 30 分钟自动把 session 进展写入 diary room，防止断电丢失</p></li></ol><p>内置 memory 工具仅保留一项职责：存储 MemPalace 的路径配置。</p><h2 id="踩过的坑"><a class="markdownIt-Anchor" href="#踩过的坑"></a> 踩过的坑</h2><p><strong>1. 内置 memory 和 MemPalace 并存时的优先级</strong></p><p>刚接进去时，两者都在，导致同一个信息存了两份，读取时有时候命中内置 memory，有时候命中 MemPalace，结果不稳定。解决办法是彻底禁用内置 memory 的写入通道，只保留读取用于兼容旧逻辑。</p><p><strong>2. embedding 模型选择影响搜索质量</strong></p><p>MemPalace 的搜索质量依赖 embedding 模型。最早用的模型对中文语义理解偏弱，&quot;登录失败&quot;和&quot;认证异常&quot;这类近义表述匹配不上。换了支持中文的 embedding 模型之后，召回率明显提升。</p><p><strong>3. 知识图谱和向量搜索的分工</strong></p><p>最初想把所有关系都塞进知识图谱，结果图数据膨胀得很快，查询延迟也上来了。后来把频繁更新、时序敏感的（如 session 进度）放在向量库，把稳定事实（项目路径、技术栈、用户偏好）放在知识图谱，分开查询再合并结果。</p><p><strong>4. session 边界和记忆持久化的平衡</strong></p><p>每次 session 结束，Hermes 内部状态会清理，但 MemPalace 是持久化的。最早没做 session 隔离，同一个 Wing 下的记忆被多个 session 交叉污染。后来每个 session 的进展单独写进 diary room，稳定的项目信息写进 general room，泾渭分明。</p><h2 id="效果"><a class="markdownIt-Anchor" href="#效果"></a> 效果</h2><p>换 session 之后，上下文还在。&quot;之前做到哪&quot;能答上来，&quot;那个 401 错误怎么处理的&quot;能找出来，&quot;用户偏好截图要整屏不要只截二维码&quot;不会被忘掉。</p><p>搜&quot;认证失败&quot;，能找到&quot;登录异常&quot;、“401”、&quot;token 过期&quot;相关内容，不用猜 key 是什么。</p><h2 id="注意"><a class="markdownIt-Anchor" href="#注意"></a> 注意</h2><ul class="lvl-0"><li class="lvl-2"><p>MemPalace 是本地存储，多设备使用需要自己处理同步</p></li><li class="lvl-2"><p>embedding 模型决定搜索上限，选型要结合自己的语料</p></li><li class="lvl-2"><p>长期运行后 sqlite 会膨胀，需要定期归档清理</p></li></ul><h2 id="改造前后对比"><a class="markdownIt-Anchor" href="#改造前后对比"></a> 改造前后对比</h2><table><thead><tr><th></th><th>内置 key-value 记忆</th><th>MemPalace 语义记忆</th></tr></thead><tbody><tr><td><strong>读取方式</strong></td><td>精确 key 匹配</td><td>语义向量相似度</td></tr><tr><td><strong>检索能力</strong></td><td>必须知道当初用什么 key</td><td>描述需求即可，意思对就能找到</td></tr><tr><td><strong>跨 session</strong></td><td>完全丢失</td><td>持久化，换 session 上下文延续</td></tr><tr><td><strong>中文语义</strong></td><td>不支持</td><td>支持中文 embedding</td></tr><tr><td><strong>知识关联</strong></td><td>无</td><td>知识图谱支持实体关系查询</td></tr><tr><td><strong>存储结构</strong></td><td>扁平的 key-value</td><td>Wings → Rooms → Drawers 分层</td></tr><tr><td><strong>外部依赖</strong></td><td>无</td><td>引入 MemPalace + ChromaDB</td></tr><tr><td><strong>运维成本</strong></td><td>无</td><td>需维护本地 sqlite 和向量库</td></tr></tbody></table><p>结论：代价是多引入一个本地依赖，换来的是检索可靠性、跨 session 记忆延续、中文语义理解。值不值看场景——偶尔用一次的 agent，key-value 够用；每天几十个任务、跨多项目的，语义记忆是刚需。</p><p>如果你的 Agent 也面临同样问题，可以从 MemoryProvider 接口入手，接入任意支持向量检索的后端都行，不一定是 MemPalace。</p>]]></content>
    
    
    <summary type="html">围绕 Hermes Agent 内置记忆的局限性，讲解如何用 MemPalace 语义记忆层替换改造</summary>
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
    <category term="AI" scheme="https://sudo.rm-rf.ink/tags/AI/"/>
    
    <category term="MemPalace" scheme="https://sudo.rm-rf.ink/tags/MemPalace/"/>
    
    <category term="Hermes Agent" scheme="https://sudo.rm-rf.ink/tags/Hermes-Agent/"/>
    
    <category term="记忆系统" scheme="https://sudo.rm-rf.ink/tags/%E8%AE%B0%E5%BF%86%E7%B3%BB%E7%BB%9F/"/>
    
  </entry>
  
  <entry>
    <title>Hello Hermes Agent</title>
    <link href="https://sudo.rm-rf.ink/*/96208538.html"/>
    <id>https://sudo.rm-rf.ink/*/96208538.html</id>
    <published>2026-04-27T15:32:00.000Z</published>
    <updated>2026-10-17T12:33:41.400Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><p>Hello Hermes Agent</p>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>daily-news-2026-04-25</title>
    <link href="https://sudo.rm-rf.ink/*/f135226f.html"/>
    <id>https://sudo.rm-rf.ink/*/f135226f.html</id>
    <published>2026-04-24T23:30:00.000Z</published>
    <updated>2026-10-17T12:33:41.400Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="糟糕！密码错误了." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="5cbd9de4dc0c3501b2c91719eb87349341d43e4d1058063888063c43432101c6">89730641517f40fad9fb11d8e72e80bf06c939f51e30e9318348e356012ae93802623e7e7460999b3f7e8ba755c0d29599ae788f4544e2d8c77419f7d87eed449b7d6813e006fe13f540d0d66182fef8c50ebd9d211e40be206647f7e00fd685b86946fa705ad4651c18ab2a320b4a69699ab0980126725a179cb3c64faa8f2509c4dddd4adebe64d5cd4207643b74cb951ade33149cd6cd51d669bce78e7df026fe1abb945332d7c0a9e2f0c8bc51b46617f418a10ed53af1ad8a5de091ee7b9161a36c5a28454693301b254151eaad572fe3718480827cbcb2b29cbbe2dd52029dfad21eac08db5c648820175597abb4a0c5ff69693595d1d3fe51de4c4f9c4194b77a63e7b407560fa73f56328d3cbee56843f26b4272acb3eeeaa0e46d01c1c94262bdc858905a4d80759515d1db386e90b995b088a668ce7196174ca5a1b9aba2fcb7975969cbd89e81d1d660e0713c098d776731fd8d15b54c7876ea503cbfbcad334fe1843e2dc94440380ae84d95a5d6f8f470f5e5e38194a5722d941a5695be5e02cf91f1b464206a372a3bf7f85681439a7be1f348cad1c7a59b72575f459e5575173933c978e1f9468637801cd2ecc88c542c3bf74f7984ed052a7e1f858719ef375ded80fdb608963fccdfdf35b5b73e174248cdea419fe4af29bf42779957ee2676458b45f6d32e46f2ae02af8a9b7cd41264e3e029dd6897628424041b07500c135840024eae37e0c2137e3a5155437364ae308c5c39140e36b2afc04c9eec03c2f97b2d91c83cf959582f8399ef4ce810df706ff7b7aa4770e22fc8b4f97fa8eab5778c4aa64fd17399d02f8f14a387d3224e0899380a27cc32933e90ac9e76e468edc8586648c2bf2f2b7e49d885122c2578a8050fc5e7ac431d6aca41092537ee2c815266ff093c737cc81cfff7252fcb4671951a05f157469629df74013c4aae3ffc9676927fac7e0cc157c22af97916efccdfea8b1f9e8129277b6a16f8a8801e305ac01b78bfe5a9f3be076ac15e47f8bf070e774537d3467e06ece04f3bcd9cabdc9f2d7e5986f886ccbad9ca116569270165cfa18d262130aa9395b06a07fa005a2241c9971c6d17b2e38fca144ad59842017ab13f64dffa53f424afccfa78e155f09f74572f34149df53be7a468706a899c91ed3f6894126137086d87882685683e6604cc231b359d28af2ce6b68b23e50b5d547d0ddb2cc0ef4a579d48a5749ef2cb71b3e2684e84da175a45bd2f070756e88ea5d2819716ca60ac6259ed3ae6f742beea2985f7ec0abc003e55484eb82e0f029fb43613a204f1df283cd88c29829fb3286f5f760c503656a982f469d829b57c7331f8615ccf2421f6d69e362559ab0ab9c26e0db9fdc5b60169f4603f89f3368464b214b2626fbc6c10068c7cf658288e680007f5cd3fa57205a4da44a6db51a7d10b1877c4c18cec4b0e1c80a1b88e3bb75ccee12f4fd580b27a0fd35ebe3d146b6cd2c840f861cf1079f6fda348e6f67e594a3788c924509d39cafcac830e701bb2b9dea32fe14c428e4f021dfd27bdfa216c4f99ba7cbacb42fc79156262a1de0f295ad09574e898bb20939969eb1c55c9921e93d0c5360a23c33a5d0cfbfae3d7610b1964936aa4a71017b7e84ee7c8486640b5deb468ee796da94689a1790e436c767cfe6dda78529cdd95388887adb6c60b71eb19cfce44c294c25167b36bb9e538872aeda496ed09920aceb9c02e6ae6ebcdd327b1eb21da43460f4da18e3eecf8ee9ed5239f039c5aea889fc5bbf0de5d8bcb781b2ebaaebb045a9727048f47d4aa42859f4888221f2bb6c7a57074d28f8c1ee9f709fc251a7992e9b2178b0f10b9df6d3c8146efcc6b1e2008f6a68531bad4d1f23e4c2c9d525cad82c2f786106926a0e7b3be3241b752cb55e38f007287781694a0d72fcf93eb93d481a501956729ba49c866b1ed193411e990566bd85d1548789122f0272a8ff6ed42ba90f8234fb3a572f4181530b4ff94bca091d02361a87ba62c3e7895afe68b983fc67d8884d8a5ee82ff5d599bf5e05f84b15959f1d82a47b49a43142a985dce74631ea4789a24dcf8530b9187be4dd8edcf7a1db4fc994134e972e0e3967ae8b1f187f6af6f87fa8f3d4f06d0ec588bbcb6dd26859105286f71db88bea24ec7791c42e4d17903b72b0b311c5631cff64616a90c1724285b76d61ee3e91638e9fed7e96efc6d352f8e13027296fbf99fb6a82bae3853d169fb8dc774300882da9c8b2f906adce800c0e27f787a5ebda05df3245ea768571b7f4c27170189604026ed50f34f365b6e7307c82521aa866051fffd33bbfa445b807b77da387370216c6783b76e7646fab9735cb78491d5549b3930ecb8c584b11b705741a87557e54d655c5030604f748e6096c510f376f95e7d6344b45de6cf998b00b2f5d57a5387145033d6a70aa280634feaa22551f2f40d2a0e522bad8e280acdc96f4bb34a9c7e384ead0d21137aa781b48f8d90bb99f8137a6743402c50d377b0c851445a4beab3e9c99d57a04da91710afd8f6eec0906d90b79009fd92d322d01e76da1c84d8afff216c6c89f2189347b323524967a112e9a23f321eab7a2cd81c5e0c9b9a6b83a2568b17086a1fdafa2a2f3caf7b37d216fc400144268d876e0cb7123af8715d4409d7edb059da1c4c4f5d5daf3e41a80fe0cdddf90d10dfd1ec641d85e2040e5c0adbbaf547b6c1dc2877a2c4968f550c0fd2cbeaf80c9a9253a2d43d07fd28d38bc455c25e99b770e1281099e43bc89dc2bad9f9dce72c9b9e06c7781556a61d0d0d63dcb8cc245dca2e5ec47cd48e91a0298dcf1ca5646cbe6c5ca06c92f4ce14de7ac0ede021ca7f9424f9b5da817930745e6357f35e8c41e2818e88c4be9c28e48cd9f4706e374adda6b7dfa8887138fb891a50f27bb2ab2f5204cae1bcfac4428dec9aeaf95fff7c52e4339b56d97f3f74332b9458bbd175f06cb61262501fa91fa1cb4c69f19c5acfae0d98f00eebe486f07404fba9e39c9b7e4a53493f676ac90e4d736660586ee7ec5a91ddb494576baf7d45bb2379379fb8e45c8dab8cb7c9a44f354e2d936d5511285b5372acd6ce43c3cbfb53fb10fe5be5a9860da4564b0f2b093c598f8826da28412b0f2f0e97b5c3a6233120708df5f7cf5a5d5d7b33054db860bcd27906301ddcd69aa7d16b389fc5565d39acdb2019435789558aad57d5fd8d97fe0ca1472c8e1bb4ceab4adc83f6372ef8e4fd7852b2d4bc6e8076620f77e7c37ca999031171a22577126c9cb628e658d9899254c45f496aa857436c49d0ded5654b36ea5a104b38fc59d5d884a3d0cc3b964d6bd646cd5cdcd78d52778ad927ad46c492c7277974caaa3b91dcfd03831f27aa621bf7b18add4d5b2ce603ed8f8c31a48fc7df64a203fce5ba5bad032943a32bb33e1dc2bc8744e1a9b7626a210a9df0c730fd07d2fd4516bba29b23ef07773d3b51f75ca95ee829dc8cc3852ae56968f8c82f9a65a9bb0eb67113c8d6c1a083ae0debb3d8d6e43b9aaede694ec2dba5248fd07b5989e61ab793e1ad549bfef018de1cba7951337014131f52bf1148cbd5fe5f6b38eeda956b7a94eb46ca7080aa509b326d89b6f4385469ee1c2be98a34aa5073a317e253f607a6f8d88c3e0261e609db0cd12b1ee41728e7a8313035c14dec7172a690a7dc2c7d2f04be1c052b1277bf5d6bdcc2f2f5cd44767140bff774ada618021a06bad294c809cc4a5c77c334d4b760dd0b79c93b13e7277d11fb007abd09091ab79f552185f7959a02aa6cbbcf221495b80cc10d54aa0106f6a0ae199a2e8e08956c7fc04df5123e43ae2008297a8da333311fc287270e475413ced86d9d380e1eb0dd7621bdee201a420d081f270fe43212fa09a288abab2f1a69c0bf4e23237f59f5e01e8aa8b17bdd4b3d97d3571e0b723237c5c6dd54e3b3e1809068e50c16539a34f8c2c60272c2cf6124c56d1a007877b272afb4edce093fa2eba940f02ac4daa9e694b90849dde72e23f0c5ed8dbeb310bda64c0d26b54e16b626639cb643fccba406792c2121bc83e0db0fda513714ca7e6feec366d5204945724a9549bb89d0aea64df80bc4c680ae8f43a68bace0d4f4a1de22629ddc8a1e16fb3fce853551902e737f383f4a53638b89d17c64283075cf01ea15fe18598cddfafb819e89348d8f69c17df657a0313cca1e009e6c2f62690ab014e716f1d689d753ae0bae8ba723815b17a797c74b0b108462a29dc81788e6f2496e9e3326cf8c335d286786742f4392d378234da067e439c648821f8ba08b6f9a57a30f72c87d39bce94e84320f757617358de936d5dbb39293ff8e89e96447e9442a6ea4398131e91bcf07ceebe0028fd26f4189dc907a7cf9b941b0cb099b16479803db82098f8dc66e81676683ea8bf113db3433bbe349dd9ad81261fb801b25df310f1e74af0634822bf5ced7e6fa499534a96605edcb2df947b61527cc4d976dd5c6aac8f5ec809eb80d6405ac878c14936d715fe31a977c67a5a4048ce8f880ce7548aa0fe3c4ad41c0f074562d64ece95e6aec0d2b2e2ee192754f6c5800e48c394fe10d7565d7763abac265bc324201917c4cfcc8bb123f98d9c578e9efdec8f748d9d448ffb1c645534fbb6f1c7e42d5af7f3187daa6fc0a094fe929d4356af4ace6e5f98cba494944db7b863ceeec0af51ca83d17bbc01bdb349830a58a7e019ef419f72523bf4b9947ac90d9bf220808bb94158888adf69194a736f6c92528f4a49986999d4a9906aafaa9</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-wave">      <input class="hbe hbe-input-field hbe-input-field-wave" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-wave" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-wave">输入密码查看内容</span>      </label>      <svg class="hbe hbe-graphic hbe-graphic-wave" width="300%" height="100%" viewBox="0 0 1200 60" preserveAspectRatio="none">        <path d="M0,56.5c0,0,298.666,0,399.333,0C448.336,56.5,513.994,46,597,46c77.327,0,135,10.5,200.999,10.5c95.996,0,402.001,0,402.001,0"></path>      </svg>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">文章加密了，需要输入密码查看</summary>
    
    
    
    <category term="daily news" scheme="https://sudo.rm-rf.ink/categories/daily-news/"/>
    
    
  </entry>
  
  <entry>
    <title>OpenClaw 0</title>
    <link href="https://sudo.rm-rf.ink/*/8b6d76da.html"/>
    <id>https://sudo.rm-rf.ink/*/8b6d76da.html</id>
    <published>2026-03-30T09:10:57.000Z</published>
    <updated>2026-03-30T09:10:57.965Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="糟糕！密码错误了." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="d3d974b29008aff606283f0e4978d7bf8e58543d1d3a787740a0ae1e7049f1ed">89730641517f40fad9fb11d8e72e80bf06c939f51e30e9318348e356012ae93802623e7e7460999b3f7e8ba755c0d29599ae788f4544e2d8c77419f7d87eed449b7d6813e006fe13f540d0d66182fef8c50ebd9d211e40be206647f7e00fd685b86946fa705ad4651c18ab2a320b4a69699ab0980126725a179cb3c64faa8f2509c4dddd4adebe64d5cd4207643b74cb951ade33149cd6cd51d669bce78e7df026fe1abb945332d7c0a9e2f0c8bc51b46617f418a10ed53af1ad8a5de091ee7b9161a36c5a28454693301b254151eaad572fe3718480827cbcb2b29cbbe2dd52029dfad21eac08db5c648820175597abb4a0c5ff69693595d1d3fe51de4c4f9c4194b77a63e7b407560fa73f56328d3cbee56843f26b4272acb3eeeaa0e46d01c1c94262bdc858905a4d80759515d1db386e90b995b088a668ce7196174ca5a1b9fde0d6c59e81ace0635b7e811b6eb4</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-wave">      <input class="hbe hbe-input-field hbe-input-field-wave" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-wave" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-wave">输入密码查看内容</span>      </label>      <svg class="hbe hbe-graphic hbe-graphic-wave" width="300%" height="100%" viewBox="0 0 1200 60" preserveAspectRatio="none">        <path d="M0,56.5c0,0,298.666,0,399.333,0C448.336,56.5,513.994,46,597,46c77.327,0,135,10.5,200.999,10.5c95.996,0,402.001,0,402.001,0"></path>      </svg>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">文章加密了，需要输入密码查看</summary>
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
  </entry>
  
  <entry>
    <title>redis主从-哨兵模式</title>
    <link href="https://sudo.rm-rf.ink/*/8f0491a1.html"/>
    <id>https://sudo.rm-rf.ink/*/8f0491a1.html</id>
    <published>2024-03-25T09:56:30.000Z</published>
    <updated>2024-03-25T09:56:31.322Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="糟糕！密码错误了." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="d3d974b29008aff606283f0e4978d7bf8e58543d1d3a787740a0ae1e7049f1ed">89730641517f40fad9fb11d8e72e80bf06c939f51e30e9318348e356012ae93802623e7e7460999b3f7e8ba755c0d29599ae788f4544e2d8c77419f7d87eed449b7d6813e006fe13f540d0d66182fef8c50ebd9d211e40be206647f7e00fd685b86946fa705ad4651c18ab2a320b4a69699ab0980126725a179cb3c64faa8f2509c4dddd4adebe64d5cd4207643b74cb951ade33149cd6cd51d669bce78e7df026fe1abb945332d7c0a9e2f0c8bc51b46617f418a10ed53af1ad8a5de091ee7b9161a36c5a28454693301b254151eaad572fe3718480827cbcb2b29cbbe2dd52029dfad21eac08db5c648820175597abb4a0c5ff69693595d1d3fe51de4c4f9c4194b77a63e7b407560fa73f56328d3cbee56843f26b4272acb3eeeaa0e46d01c1c94262bdc858905a4d80759515d1db386e90b995b088a668ce7196174ca5a1b9fde0d6c59e81ace0635b7e811b6eb4</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-wave">      <input class="hbe hbe-input-field hbe-input-field-wave" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-wave" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-wave">输入密码查看内容</span>      </label>      <svg class="hbe hbe-graphic hbe-graphic-wave" width="300%" height="100%" viewBox="0 0 1200 60" preserveAspectRatio="none">        <path d="M0,56.5c0,0,298.666,0,399.333,0C448.336,56.5,513.994,46,597,46c77.327,0,135,10.5,200.999,10.5c95.996,0,402.001,0,402.001,0"></path>      </svg>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">文章加密了，需要输入密码查看</summary>
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
  </entry>
  
  <entry>
    <title>rust-if-let简洁控制流</title>
    <link href="https://sudo.rm-rf.ink/*/eec35d0e.html"/>
    <id>https://sudo.rm-rf.ink/*/eec35d0e.html</id>
    <published>2024-03-14T00:41:12.000Z</published>
    <updated>2024-03-19T09:44:54.201Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h1 id="if-let-控制流"><a class="markdownIt-Anchor" href="#if-let-控制流"></a> if let 控制流</h1>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="if" scheme="https://sudo.rm-rf.ink/tags/if/"/>
    
    <category term="let" scheme="https://sudo.rm-rf.ink/tags/let/"/>
    
    <category term="rust" scheme="https://sudo.rm-rf.ink/tags/rust/"/>
    
  </entry>
  
  <entry>
    <title>rust-枚举与模式匹配</title>
    <link href="https://sudo.rm-rf.ink/*/7d69317e.html"/>
    <id>https://sudo.rm-rf.ink/*/7d69317e.html</id>
    <published>2024-03-13T09:35:29.000Z</published>
    <updated>2024-03-14T00:41:38.964Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h1 id="枚举"><a class="markdownIt-Anchor" href="#枚举"></a> 枚举</h1><blockquote><p>结构体给予你将字段和数据聚合在一起的方法，像 <code>Rectangle</code> 结构体有 <code>width</code> 和 <code>height</code> 两个字段。而枚举给予你一个途径去声明某个值是一个集合中的一员。比如，我们想让 <code>Rectangle</code> 是一些形状的集合，包含 <code>Circle</code> 和 <code>Triangle</code> 。为了做到这个，Rust 提供了枚举类型。</p></blockquote><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">IpAddrKind</span> &#123;</span><br><span class="line">    <span class="title function_ invoke__">V4</span>(<span class="type">u8</span>,<span class="type">u8</span>,<span class="type">u8</span>,<span class="type">u8</span>),</span><br><span class="line">    <span class="title function_ invoke__">V6</span>(<span class="type">String</span>),</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Message</span>&#123;</span><br><span class="line">    Quit,</span><br><span class="line">    Move&#123;x: <span class="type">i32</span>,y:<span class="type">i32</span>&#125;,</span><br><span class="line">    <span class="title function_ invoke__">Write</span>(<span class="type">String</span>),</span><br><span class="line">    <span class="title function_ invoke__">ChangeColor</span>(<span class="type">i32</span>,<span class="type">i32</span>,<span class="type">i32</span>),</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span> <span class="title class_">Message</span>&#123;</span><br><span class="line">    <span class="keyword">fn</span> <span class="title function_">call</span>(&amp;<span class="keyword">self</span>)&#123;</span><br><span class="line">        <span class="built_in">println!</span>(<span class="string">&quot;self is &#123;:?&#125;&quot;</span>,&amp;<span class="keyword">self</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;Hello, world!&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">four</span> = IpAddrKind::<span class="title function_ invoke__">V4</span>(<span class="number">127</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">six</span> = IpAddrKind::<span class="title function_ invoke__">V6</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;::1&quot;</span>));</span><br><span class="line"></span><br><span class="line">    dbg!(&amp;four);</span><br><span class="line">    dbg!(&amp;six);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">m</span> = Message::Move &#123; x: <span class="number">1</span>, y: <span class="number">2</span> &#125;;</span><br><span class="line">    m.<span class="title function_ invoke__">call</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="match匹配模式"><a class="markdownIt-Anchor" href="#match匹配模式"></a> match匹配模式</h1><h2 id="option枚举"><a class="markdownIt-Anchor" href="#option枚举"></a> Option枚举</h2><blockquote><p><code>Option</code> 是标准库定义的另一个枚举。<code>Option</code> 类型应用广泛因为它编码了一个非常普遍的场景，即一个值要么有值要么没值。</p></blockquote><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Coin</span>&#123;</span><br><span class="line">    Penny,</span><br><span class="line">    Nickel,</span><br><span class="line">    Dime,</span><br><span class="line">    Quarter,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;Hello, world!&quot;</span>);</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">v</span> = <span class="title function_ invoke__">value_in_cents</span>(Coin::Quarter);</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;value_in_cents(coin) = &#123;&#125;&quot;</span>, v);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">value_in_cents</span>(coin: Coin) <span class="punctuation">-&gt;</span> <span class="type">u32</span> &#123;</span><br><span class="line">    <span class="keyword">match</span> coin &#123;</span><br><span class="line">        Coin::Penny =&gt; <span class="number">1</span>,</span><br><span class="line">        Coin::Nickel =&gt; <span class="number">5</span>,</span><br><span class="line">        Coin::Dime =&gt; <span class="number">10</span>,</span><br><span class="line">        Coin::Quarter =&gt; <span class="number">25</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="rust" scheme="https://sudo.rm-rf.ink/tags/rust/"/>
    
    <category term="enum" scheme="https://sudo.rm-rf.ink/tags/enum/"/>
    
  </entry>
  
  <entry>
    <title>rust-方法语法</title>
    <link href="https://sudo.rm-rf.ink/*/d1274d86.html"/>
    <id>https://sudo.rm-rf.ink/*/d1274d86.html</id>
    <published>2024-03-13T09:18:32.000Z</published>
    <updated>2024-03-13T09:35:30.501Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h1 id="方法语法"><a class="markdownIt-Anchor" href="#方法语法"></a> 方法语法</h1><blockquote><p><strong>方法</strong>（method）与函数类似：它们使用 <code>fn</code> 关键字和名称声明，可以拥有参数和返回值，同时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的，因为它们在结构体的上下文中被定义（或者是枚举或 trait 对象的上下文，并且它们第一个参数总是 <code>self</code>，它代表调用该方法的结构体实例。</p></blockquote><h2 id="方法定义"><a class="markdownIt-Anchor" href="#方法定义"></a> 方法定义</h2><p>使用<code>impl</code>块为结构定义方法；</p><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Rectangle</span> &#123;</span><br><span class="line">    width: <span class="type">u32</span>,</span><br><span class="line">    height: <span class="type">u32</span>,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span> <span class="title class_">Rectangle</span> &#123;</span><br><span class="line">    <span class="keyword">fn</span> <span class="title function_">area</span>(&amp;<span class="keyword">self</span>) <span class="punctuation">-&gt;</span> <span class="type">u32</span> &#123;</span><br><span class="line">        <span class="keyword">self</span>.width * <span class="keyword">self</span>.height</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">fn</span> <span class="title function_">can_hold</span>(&amp;<span class="keyword">self</span>,target: &amp;Rectangle ) <span class="punctuation">-&gt;</span> <span class="type">bool</span> &#123;</span><br><span class="line">      <span class="keyword">self</span>.width &gt; target.width &amp;&amp; <span class="keyword">self</span>.height &gt; target.height</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 关联函数经常被用作返回一个结构体新实例的构造函数。</span></span><br><span class="line">  <span class="comment">// 这些函数的名称通常为 new ，但 new 并不是一个关键字。</span></span><br><span class="line">    <span class="keyword">fn</span> <span class="title function_">square</span>(size: <span class="type">u32</span>) <span class="punctuation">-&gt;</span> <span class="keyword">Self</span>&#123;</span><br><span class="line">        <span class="keyword">Self</span> &#123;</span><br><span class="line">            width: size,</span><br><span class="line">            height: size,</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">rect</span> = Rectangle::<span class="title function_ invoke__">square</span>(<span class="number">30</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">rect1</span> = Rectangle &#123; width: <span class="number">10</span>, height: <span class="number">30</span> &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">rect2</span> = Rectangle &#123; width: <span class="number">60</span>, height: <span class="number">80</span> &#125;;</span><br><span class="line">    dbg!(&amp;rect);</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;The area of the rectangle is &#123;&#125; square pixels.&quot;</span>, rect.<span class="title function_ invoke__">area</span>());</span><br><span class="line">  <span class="built_in">println!</span>(<span class="string">&quot;Can rect hold rect1? &#123;&#125;&quot;</span>, rect.<span class="title function_ invoke__">can_hold</span>(&amp;rect1));</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;Can rect hold rect2? &#123;&#125;&quot;</span>, rect.<span class="title function_ invoke__">can_hold</span>(&amp;rect2));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="rust" scheme="https://sudo.rm-rf.ink/tags/rust/"/>
    
    <category term="method" scheme="https://sudo.rm-rf.ink/tags/method/"/>
    
    <category term="syntax" scheme="https://sudo.rm-rf.ink/tags/syntax/"/>
    
  </entry>
  
  <entry>
    <title>rust-结构定义和实例化</title>
    <link href="https://sudo.rm-rf.ink/*/e0d5ed17.html"/>
    <id>https://sudo.rm-rf.ink/*/e0d5ed17.html</id>
    <published>2024-03-13T08:53:22.000Z</published>
    <updated>2024-03-13T09:23:11.291Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h1 id="结构定义"><a class="markdownIt-Anchor" href="#结构定义"></a> 结构定义</h1><blockquote><p>定义结构体，需要使用 <code>struct</code> 关键字并为整个结构体提供一个名字。结构体的名字需要描述它所组合的数据的意义。接着，在大括号中，定义每一部分数据的名字和类型，我们称为 <strong>字段</strong>（<em>field</em>）。</p></blockquote><p>以下演示了结构定义、打印对象、debug打印对象；</p><ul class="lvl-0"><li class="lvl-2"><p>可以定义有字段和无字段结构，包括类似<code>Tuple</code>（元组）的方式定义；</p></li><li class="lvl-2"><p><code>println!</code>和<code>dbg!</code>打印对象需要在结构上添加外部属性 <code>#[derive(Debug)]</code>；</p></li><li class="lvl-2"><p><code>dbg!</code>宏打印需要注意值引用；</p></li></ul><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">User</span> &#123;</span><br><span class="line">    active: <span class="type">bool</span>,</span><br><span class="line">    username: <span class="type">String</span>,</span><br><span class="line">    email: <span class="type">String</span>,</span><br><span class="line">    sign_in_count: <span class="type">u64</span>,</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Color</span>(<span class="type">i32</span>,<span class="type">i32</span>,<span class="type">i32</span>);</span><br><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Point</span>(<span class="type">i32</span>,<span class="type">i32</span>, <span class="type">i32</span>);</span><br><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">AlwaysEqual</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Square</span>(<span class="type">u32</span>,<span class="type">u32</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;Hello, world!&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">user</span> =  <span class="title function_ invoke__">build_user</span>(<span class="string">&quot;dong33@163.com&quot;</span>,<span class="string">&quot;dong33&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;user is &#123;:?&#125;&quot;</span>,user);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">user1</span> = User&#123;</span><br><span class="line">        active: <span class="literal">true</span>,</span><br><span class="line">        username: user.username,</span><br><span class="line">        email: user.email,</span><br><span class="line">        sign_in_count: <span class="number">1</span>,</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;user1 is &#123;:?&#125;&quot;</span>,user1);</span><br><span class="line">    dbg!(user1);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">black</span> = <span class="title function_ invoke__">Color</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;black is &#123;:?&#125;&quot;</span>,black);</span><br><span class="line">    dbg!(black);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">origin</span> = <span class="title function_ invoke__">Point</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;origin is &#123;:?&#125;&quot;</span>,origin);</span><br><span class="line">    dbg!(origin);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">subject</span> = AlwaysEqual;</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;subject is &#123;:?&#125;&quot;</span>,subject);</span><br><span class="line">    dbg!(subject);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">width</span> = <span class="number">30</span>;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">height</span> = <span class="number">50</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot; area is &#123;&#125;&quot;</span>,<span class="title function_ invoke__">area</span>(width, height));</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">rect</span> = <span class="title function_ invoke__">Square</span>(<span class="number">30</span>,<span class="number">50</span>);</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;rect is &#123;:?&#125;&quot;</span>,rect);</span><br><span class="line">    dbg!(&amp;rect);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;square area is &#123;&#125;&quot;</span>,<span class="title function_ invoke__">area_square</span>(&amp;rect));</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">build_user</span>(email: &amp;<span class="type">str</span>,username: &amp;<span class="type">str</span>) <span class="punctuation">-&gt;</span> User &#123;</span><br><span class="line">    User &#123;</span><br><span class="line">        active: <span class="literal">true</span>,</span><br><span class="line">        username: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(username),</span><br><span class="line">        email: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(email),</span><br><span class="line">        sign_in_count: <span class="number">1</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">area</span>(width: <span class="type">u32</span>,height: <span class="type">u32</span>) <span class="punctuation">-&gt;</span> <span class="type">u32</span>&#123;</span><br><span class="line">    width * height</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">area_square</span>(square: &amp;Square) <span class="punctuation">-&gt;</span> <span class="type">u32</span>&#123;</span><br><span class="line">    square.<span class="number">0</span> * square.<span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="rust" scheme="https://sudo.rm-rf.ink/tags/rust/"/>
    
    <category term="struct" scheme="https://sudo.rm-rf.ink/tags/struct/"/>
    
  </entry>
  
  <entry>
    <title>rust入门</title>
    <link href="https://sudo.rm-rf.ink/*/94fe59ce.html"/>
    <id>https://sudo.rm-rf.ink/*/94fe59ce.html</id>
    <published>2024-03-11T01:30:48.000Z</published>
    <updated>2024-03-13T08:53:31.213Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><h1 id="cargo是什么"><a class="markdownIt-Anchor" href="#cargo是什么"></a> Cargo是什么？</h1><p><code>Cargo</code>是rust的构建工具、包管理器；</p><h3 id="crate是什么"><a class="markdownIt-Anchor" href="#crate是什么"></a> crate是什么？</h3><p>  crate类似npm package或ruby gem，类似<code>依赖包</code>的意思；</p><h1 id="rust和动态语言对比"><a class="markdownIt-Anchor" href="#rust和动态语言对比"></a> rust和动态语言对比</h1><h1 id="rust库"><a class="markdownIt-Anchor" href="#rust库"></a> rust库</h1><h3 id="std-io标准库"><a class="markdownIt-Anchor" href="#std-io标准库"></a> std io标准库</h3><h3 id="let声明变量"><a class="markdownIt-Anchor" href="#let声明变量"></a> let声明变量</h3><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">apples</span> = <span class="number">5</span>; <span class="comment">// 不可变</span></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">bananas</span> = <span class="number">5</span>; <span class="comment">// 可变</span></span><br></pre></td></tr></table></figure><h3 id="整型"><a class="markdownIt-Anchor" href="#整型"></a> 整型</h3><table><thead><tr><th>长度</th><th>有符号</th><th>无符号</th></tr></thead><tbody><tr><td>8-bit</td><td>i8</td><td>U8</td></tr><tr><td>16-bit</td><td>i16</td><td>u16</td></tr><tr><td>32-bit</td><td>i32</td><td>u32</td></tr><tr><td>64-bit</td><td>i64</td><td>U64</td></tr><tr><td>128-bit</td><td>i128</td><td>u128</td></tr><tr><td>arch（由CPU架构决定大小 x86为32位，x64为64位）</td><td>isize</td><td>Usize</td></tr></tbody></table><table><thead><tr><th>数字字面值</th><th>例子</th></tr></thead><tbody><tr><td>Decimal(十进制)</td><td>98_222</td></tr><tr><td>Hex(十六进制)</td><td>0xff</td></tr><tr><td>Octal(八进制)</td><td>0o77</td></tr><tr><td>Binary(二进制)</td><td>0b1111_0000</td></tr><tr><td>Byte(单字节字符)(仅限于u8)</td><td>b’A’</td></tr></tbody></table><h3 id="浮点型"><a class="markdownIt-Anchor" href="#浮点型"></a> 浮点型</h3><p>Rust的浮点数类型是 <code>f32</code>和<code>f64</code>,分别占32位和64位，默认类型是<code>f64</code></p><p>浮点数采用 IEEE-754 标准表示。<code>f32</code> 是单精度浮点数，<code>f64</code> 是双精度浮点数。</p><h3 id="布尔型"><a class="markdownIt-Anchor" href="#布尔型"></a> 布尔型</h3><p>Rust的布尔类型有两个值: <code>true</code>和<code>false</code>,使用 <code>bool</code>表示；</p><h3 id="字符类型"><a class="markdownIt-Anchor" href="#字符类型"></a> 字符类型</h3><p>Rust的 <code>char</code>类型是语言中原生的字符类型；使用 <code>''</code>声明字符类型，字符串使用 <code>&quot;&quot;</code>声明；</p><h3 id="复合类型"><a class="markdownIt-Anchor" href="#复合类型"></a> 复合类型</h3><p>Rust有两个原生复合类型: 元组（tuple）和数组 （array）</p><h4 id="元组-tuple"><a class="markdownIt-Anchor" href="#元组-tuple"></a> 元组 Tuple</h4><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">x</span>: (<span class="type">i32</span>, <span class="type">f64</span>, <span class="type">u8</span>) = (<span class="number">500</span>, <span class="number">6.4</span>, <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">five_hundred</span> = x.<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">six_point_four</span> = x.<span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">one</span> = x.<span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="数组-array"><a class="markdownIt-Anchor" href="#数组-array"></a> 数组 Array</h4><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">a</span>: [<span class="type">i32</span>; <span class="number">5</span>] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="variable">first</span> = a[<span class="number">0</span>];</span><br><span class="line"><span class="keyword">let</span> <span class="variable">end</span> = a[<span class="number">4</span>];</span><br></pre></td></tr></table></figure><h3 id="fn-main"><a class="markdownIt-Anchor" href="#fn-main"></a> fn、main</h3><p><code>fn</code>用于声明函数，<code>main</code>函数为程序入口；</p><p>在函数声明中，必须声明每个参数的类型。</p><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>()&#123;</span><br><span class="line"><span class="title function_ invoke__">print_labeled_measurement</span>(<span class="number">5</span>,<span class="string">&#x27;h&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">print_labeled_measurement</span>(value: <span class="type">i32</span>,unit_label: <span class="type">char</span>)&#123;</span><br><span class="line">  <span class="built_in">println!</span>(<span class="string">&quot;The measurement is: &#123;value&#125;&#123;unit_label&#125;&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">five</span>() <span class="punctuation">-&gt;</span> <span class="type">i32</span>&#123;</span><br><span class="line">  <span class="number">5</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>语句和表达式的区别,语句需要<code>;</code>修饰，表达式不需要。</p><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">x</span> = <span class="title function_ invoke__">plus_one</span>(<span class="number">5</span>); <span class="comment">//语句</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;The value of x is: &#123;x&#125;&quot;</span>); <span class="comment">//语句</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">plus_one</span>(x: <span class="type">i32</span>) <span class="punctuation">-&gt;</span> <span class="type">i32</span> &#123;</span><br><span class="line">    x + <span class="number">1</span> <span class="comment">//表达式</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="练习-斐波那契数列"><a class="markdownIt-Anchor" href="#练习-斐波那契数列"></a> <strong>练习-斐波那契数列</strong></h5><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="title function_ invoke__">fibonacci</span>(<span class="number">22</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">fibonacci</span>(n: <span class="type">i32</span>) <span class="punctuation">-&gt;</span> <span class="type">i32</span> &#123;</span><br><span class="line">    <span class="keyword">match</span> n &#123;</span><br><span class="line">        <span class="number">0</span> =&gt; <span class="number">0</span>,</span><br><span class="line">        <span class="number">1</span> =&gt;<span class="number">1</span>,</span><br><span class="line">        <span class="number">2</span> =&gt; <span class="number">1</span>,</span><br><span class="line">        _ =&gt; <span class="title function_ invoke__">fibonacci</span>(n-<span class="number">1</span>) + <span class="title function_ invoke__">fibonacci</span>(n-<span class="number">2</span>),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="注释"><a class="markdownIt-Anchor" href="#注释"></a> 注释</h3><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="comment">//这是第一行注释</span></span><br><span class="line"><span class="comment">//这是第二行注释</span></span><br><span class="line"><span class="comment">//这是第三行注释</span></span><br></pre></td></tr></table></figure><h4 id="文档注释"><a class="markdownIt-Anchor" href="#文档注释"></a> 文档注释</h4><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="comment">///这是第一行注释</span></span><br><span class="line"><span class="comment">///这是第二行注释</span></span><br><span class="line"><span class="comment">///这是第三行注释</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//! #这是第一行注释</span></span><br><span class="line"><span class="comment">//!</span></span><br><span class="line"><span class="comment">//! ###这是第三行注释</span></span><br></pre></td></tr></table></figure><h3 id="if表达式"><a class="markdownIt-Anchor" href="#if表达式"></a> if表达式</h3><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>()&#123;</span><br><span class="line">  <span class="keyword">let</span> <span class="variable">number</span> = <span class="number">3</span>;</span><br><span class="line">  <span class="keyword">if</span> number &lt; <span class="number">3</span> &#123;</span><br><span class="line">    printlin!(<span class="string">&quot;Number is less than 3 &quot;</span>)</span><br><span class="line">  &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">     printlin!(<span class="string">&quot;Number is greater than or equal to 3 &quot;</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="在let语句中使用if-else"><a class="markdownIt-Anchor" href="#在let语句中使用if-else"></a> 在let语句中使用if else</h4><p>提示: if else的分支类型要匹配，否则会提示编译错误</p><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>()&#123;</span><br><span class="line"><span class="keyword">let</span> <span class="variable">number</span> = <span class="number">3</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="variable">result</span> = <span class="keyword">if</span> number &gt;= <span class="number">3</span> &#123; <span class="number">10</span> &#125; <span class="keyword">else</span> &#123;<span class="number">0</span>&#125;;</span><br><span class="line"><span class="built_in">println!</span>(<span class="string">&quot;The value of number is: &#123;result&#125;&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="loop循环"><a class="markdownIt-Anchor" href="#loop循环"></a> loop循环</h3><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut  </span><span class="variable">count</span> = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="symbol">&#x27;counting_up</span>: <span class="keyword">loop</span> &#123;</span><br><span class="line">        <span class="built_in">println!</span>(<span class="string">&quot;count = &#123;count&#125;&quot;</span>);</span><br><span class="line">        <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">remaining</span> = <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">loop</span>&#123;</span><br><span class="line">            <span class="built_in">println!</span>(<span class="string">&quot;remaining = &#123;remaining&#125;&quot;</span>);</span><br><span class="line">            <span class="keyword">if</span> remaining == <span class="number">9</span> &#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> count == <span class="number">2</span>&#123;</span><br><span class="line">                <span class="keyword">break</span> <span class="symbol">&#x27;counting_up</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            remaining -= <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        count += <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;End count = &#123;count&#125;&quot;</span>)</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="while循环"><a class="markdownIt-Anchor" href="#while循环"></a> while循环</h3><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>()&#123;</span><br><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">number</span> = <span class="number">3</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> number != <span class="number">0</span> &#123;</span><br><span class="line">        <span class="built_in">println!</span>(<span class="string">&quot;&#123;number&#125;&quot;</span>);</span><br><span class="line">        number -= <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;End&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="for循环"><a class="markdownIt-Anchor" href="#for循环"></a> for循环</h3><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>()&#123;</span><br><span class="line"><span class="keyword">let</span> <span class="variable">a</span> = [<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>,<span class="number">40</span>,<span class="number">50</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> <span class="variable">element</span> <span class="keyword">in</span> a &#123;</span><br><span class="line">        <span class="built_in">println!</span>(<span class="string">&quot;the value is: &#123;element&#125;&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="match-分支"><a class="markdownIt-Anchor" href="#match-分支"></a> match 分支</h3><p>用于分支判断，类似其他语言的switch(condition){}</p><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">guess</span>: <span class="type">u32</span> = <span class="keyword">match</span> guess.<span class="title function_ invoke__">trim</span>().<span class="title function_ invoke__">parse</span>() &#123;</span><br><span class="line">            <span class="title function_ invoke__">Ok</span>(num) =&gt; num,</span><br><span class="line">            <span class="title function_ invoke__">Err</span>(_) =&gt; <span class="keyword">continue</span>,</span><br><span class="line">        &#125;;</span><br></pre></td></tr></table></figure><h3 id="const-常量"><a class="markdownIt-Anchor" href="#const-常量"></a> const 常量</h3><p>常量和其他语言类似，约定大写+<code>_</code>命名</p><h3 id="所有权ownership"><a class="markdownIt-Anchor" href="#所有权ownership"></a> 所有权(ownership)</h3><ul class="lvl-0"><li class="lvl-2"><p>堆: 先进先出；</p></li><li class="lvl-2"><p>栈: 先进后出；</p></li></ul><h4 id="所有权规则"><a class="markdownIt-Anchor" href="#所有权规则"></a> 所有权规则</h4><ul class="lvl-0"><li class="lvl-2"><p>rust 中的每一个值都有一个 <code>owner</code>；</p></li><li class="lvl-2"><p>值在任一时刻有且只有一个<code>owner</code>；</p></li><li class="lvl-2"><p>当<code>owner</code>离开作用域，这个值将被丢弃；</p></li></ul><h4 id="变量作用域"><a class="markdownIt-Anchor" href="#变量作用域"></a> 变量作用域</h4><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line">&#123;                      <span class="comment">// s 在这里无效，它尚未声明</span></span><br><span class="line">        <span class="keyword">let</span> <span class="variable">s</span> = <span class="string">&quot;hello&quot;</span>;   <span class="comment">// 从此处起，s 是有效的</span></span><br><span class="line">        <span class="comment">// 使用 s</span></span><br><span class="line"> &#125;                      <span class="comment">// 此作用域已结束，s 不再有效</span></span><br></pre></td></tr></table></figure><h3 id="string-类型"><a class="markdownIt-Anchor" href="#string-类型"></a> String 类型</h3><blockquote><p>如果你在其他语言中听说过术语 <strong>浅拷贝</strong>（<em>shallow copy</em>）和 <strong>深拷贝</strong>（<em>deep copy</em>），那么拷贝指针、长度和容量而不拷贝数据可能听起来像浅拷贝。不过因为 Rust 同时使第一个变量无效了，这个操作被称为 <strong>移动</strong>（<em>move</em>），而不是叫做浅拷贝。上面的例子可以解读为 <code>s1</code> 被 <strong>移动</strong> 到了 <code>s2</code> 中。</p></blockquote><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">s1</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line"><span class="keyword">let</span> <span class="variable">s2</span> = s1;</span><br><span class="line">  <span class="comment">//-- value moved here</span></span><br><span class="line"><span class="built_in">println!</span>(<span class="string">&quot;&#123;s1&#125;&quot;</span>);</span><br><span class="line"><span class="comment">//^^^^ value borrowed here after move</span></span><br></pre></td></tr></table></figure><h3 id="copy类型"><a class="markdownIt-Anchor" href="#copy类型"></a> <code>Copy</code>类型</h3><ul class="lvl-0"><li class="lvl-2"><p>所有整数类型，比如 <code>u32</code>。</p></li><li class="lvl-2"><p>布尔类型，<code>bool</code>，它的值是 <code>true</code> 和 <code>false</code>。</p></li><li class="lvl-2"><p>所有浮点数类型，比如 <code>f64</code>。</p></li><li class="lvl-2"><p>字符类型，<code>char</code>。</p></li><li class="lvl-2"><p>元组，当且仅当其包含的类型也都实现 <code>Copy</code> 的时候。比如，<code>(i32, i32)</code> 实现了 <code>Copy</code>，但 <code>(i32, String)</code> 就没有。</p></li></ul><h3 id="引用references与借用"><a class="markdownIt-Anchor" href="#引用references与借用"></a> 引用（References）与借用</h3><p><code>&amp;</code>语法让我们创建一个指向的引用，但并不拥有。</p><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">s1</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">len</span> = <span class="title function_ invoke__">calculate_length</span>(&amp;s1);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;The length of &#x27;&#123;&#125;&#x27; is &#123;&#125;.&quot;</span>, s1, len);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">calculate_length</span>(s: &amp;<span class="type">String</span>) <span class="punctuation">-&gt;</span> <span class="type">usize</span> &#123;</span><br><span class="line">    s.<span class="title function_ invoke__">len</span>()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>&amp; mut</code> 可变引用，可修改应用的值；</p><p>限制:</p><ul class="lvl-0"><li class="lvl-2"><p>在任意给定时间，<strong>要么</strong> 只能有一个可变引用，<strong>要么</strong> 只能有多个不可变引用。</p></li><li class="lvl-2"><p>引用必须总是有效的。</p></li></ul><p><strong>数据竞争</strong>（<em>data race</em>）类似于竞态条件，它可由这三个行为造成：</p><ul class="lvl-0"><li class="lvl-2"><p>两个或更多指针同时访问同一数据。</p></li><li class="lvl-2"><p>至少有一个指针被用来写入数据。</p></li><li class="lvl-2"><p>没有同步数据访问的机制。</p></li></ul><figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">s1</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">    <span class="title function_ invoke__">change</span>(&amp;<span class="keyword">mut</span> s1);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;The length of &#x27;&#123;&#125;&#x27; is &#123;&#125;.&quot;</span>, s1, s1.<span class="title function_ invoke__">len</span>());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">change</span>(s: &amp;<span class="keyword">mut</span> <span class="type">String</span>)&#123;</span><br><span class="line">    s.<span class="title function_ invoke__">push_str</span>(<span class="string">&quot;, world!!!!&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="slice类型"><a class="markdownIt-Anchor" href="#slice类型"></a> Slice类型</h3><blockquote><p><em>slice</em> 允许你引用集合中一段连续的元素序列，而不用引用整个集合。slice 是一种引用，所以它没有所有权。</p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="cargo" scheme="https://sudo.rm-rf.ink/tags/cargo/"/>
    
    <category term="rustc" scheme="https://sudo.rm-rf.ink/tags/rustc/"/>
    
    <category term="rustup" scheme="https://sudo.rm-rf.ink/tags/rustup/"/>
    
  </entry>
  
  <entry>
    <title>Transformer模型</title>
    <link href="https://sudo.rm-rf.ink/*/e4b8a22b.html"/>
    <id>https://sudo.rm-rf.ink/*/e4b8a22b.html</id>
    <published>2024-02-22T03:01:14.000Z</published>
    <updated>2024-02-22T03:30:25.314Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><p>  Transformer模型最早是由Google的研究团队在2017年提出的，并在论文《Attention is All You Need》<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> 中进行了详细的介绍。这个模型是为了解决自然语言处理（NLP）任务中的一些问题而设计的，特别是为了克服传统循环神经网络（RNN）和长短期记忆网络（LSTM）在处理长序列时的局限性，如梯度消失或梯度爆炸问题。</p><p>  Transformer模型的核心思想是使用自注意力机制（Self-Attention Mechanism）来捕捉输入序列中的依赖关系。这种机制允许模型在处理每个输入元素时，都能够关注到输入序列中的所有其他元素，从而能够捕捉到更长的依赖关系。此外，Transformer模型还采用了位置编码（Positional Encoding）来弥补模型本身不具备处理序列顺序的能力。</p><p>  Transformer模型由两部分组成：编码器（Encoder）和解码器（Decoder）。编码器负责将输入序列转换为一系列向量表示，而解码器则负责根据这些向量表示生成输出序列。这两部分都由多个相同的层堆叠而成，每一层都包含一个多头自注意力子层和一个简单的全连接前馈神经网络。</p><p>  由于Transformer模型不依赖RNN的顺序结构，因此它可以实现高效的并行化训练，这使得它在处理大规模数据集时具有显著的优势。此外，Transformer模型的强大表示能力和灵活性使得它在多个NLP任务上都取得了显著的效果，成为了自然语言处理领域的一种主流模型。</p><p>  总的来说，Transformer模型是Google研究团队在2017年提出的一种基于自注意力机制的深度学习模型，它的出现为自然语言处理领域的发展带来了革命性的突破。</p><p>引用:</p><ul class="lvl-0"><li class="lvl-2"><p><a href="https://zhuanlan.zhihu.com/p/647249972">Text-to-SQL小白入门（一）</a></p></li><li class="lvl-2"><p><a href="https://zhuanlan.zhihu.com/p/650407036">Text-to-SQL小白入门（二）</a></p></li></ul><p>原论文:</p><div class="row">    <embed src="/images/1706.03762.pdf" width="100%" height="550" type="application/pdf"></div><hr class="footnotes-sep"><section class="footnotes"><ol class="footnotes-list"><li id="fn1" class="footnote-item"><p>《Attention is All You Need》 <a href="#fnref1" class="footnote-backref">↩︎</a></p></li></ol></section>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="机器学习" scheme="https://sudo.rm-rf.ink/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
    
    <category term="NLP" scheme="https://sudo.rm-rf.ink/tags/NLP/"/>
    
    <category term="text2sql" scheme="https://sudo.rm-rf.ink/tags/text2sql/"/>
    
  </entry>
  
  <entry>
    <title>笔记4-《程序员数学-1》</title>
    <link href="https://sudo.rm-rf.ink/*/c88b93d0.html"/>
    <id>https://sudo.rm-rf.ink/*/c88b93d0.html</id>
    <published>2024-02-19T01:07:47.000Z</published>
    <updated>2024-02-22T07:52:55.056Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
  </entry>
  
  <entry>
    <title>开年大吉，工作顺利！</title>
    <link href="https://sudo.rm-rf.ink/*/73b21f0a.html"/>
    <id>https://sudo.rm-rf.ink/*/73b21f0a.html</id>
    <published>2024-02-18T07:00:20.000Z</published>
    <updated>2024-02-18T07:15:06.086Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><div style="display:flex;justify-content: center;">    <div>      <img width="400" height="auto" src="../images/image-20240218151047849.png" alt="龙年大吉大利" style="text-align: center;">      <div style="text-align: center;user-select: none;">图片：“龙年大吉大利”</div>    </div>  </div>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
  </entry>
  
  <entry>
    <title>研发年终总结</title>
    <link href="https://sudo.rm-rf.ink/*/72bee84d.html"/>
    <id>https://sudo.rm-rf.ink/*/72bee84d.html</id>
    <published>2024-02-05T02:52:56.000Z</published>
    <updated>2024-02-18T07:06:12.600Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="糟糕！密码错误了." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="d750b976d0af0dae30016627668be28e6d2795db96258477d297a1da59746216">89730641517f40fad9fb11d8e72e80bf06c939f51e30e9318348e356012ae93802623e7e7460999b3f7e8ba755c0d29599ae788f4544e2d8c77419f7d87eed449b7d6813e006fe13f540d0d66182fef8c50ebd9d211e40be206647f7e00fd685b86946fa705ad4651c18ab2a320b4a69699ab0980126725a179cb3c64faa8f2509c4dddd4adebe64d5cd4207643b74cb951ade33149cd6cd51d669bce78e7df026fe1abb945332d7c0a9e2f0c8bc51b46617f418a10ed53af1ad8a5de091ee7b9161a36c5a28454693301b254151eaad572fe3718480827cbcb2b29cbbe2dd52029dfad21eac08db5c648820175597abb4a0c5ff69693595d1d3fe51de4c4f9c4194b77a63e7b407560fa73f56328d3cbee56843f26b4272acb3eeeaa0e46d0184c4df4adb62aec6770ccb2861933b80934badbd52b2032fb7d7fa8ea0a30401ead330577c4c8a85a72eb63f81f2d244582b0bf85438efa61c49e9528be85df7860fd17b3214829fa137b0184419f3fed24cb821d072633aec08c83b1784e73254f5ed31d204d1b341591704aec00a4d084e8d5095986f4aacc7046f1624418b2ec37bd0d60f984141aac07614e7fb2771146fa6ae68844ab7397c9522ac715b</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-wave">      <input class="hbe hbe-input-field hbe-input-field-wave" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-wave" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-wave">输入密码查看内容</span>      </label>      <svg class="hbe hbe-graphic hbe-graphic-wave" width="300%" height="100%" viewBox="0 0 1200 60" preserveAspectRatio="none">        <path d="M0,56.5c0,0,298.666,0,399.333,0C448.336,56.5,513.994,46,597,46c77.327,0,135,10.5,200.999,10.5c95.996,0,402.001,0,402.001,0"></path>      </svg>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">文章加密了，需要输入密码查看</summary>
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
  </entry>
  
  <entry>
    <title>表单中心功能清单</title>
    <link href="https://sudo.rm-rf.ink/*/74a10861.html"/>
    <id>https://sudo.rm-rf.ink/*/74a10861.html</id>
    <published>2024-01-30T00:58:31.000Z</published>
    <updated>2024-02-05T07:50:45.258Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="糟糕！密码错误了." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="d4fdaf5f778ad2b7f7839b20408f063600471c71adaf758c95e523234574a9d6">89730641517f40fad9fb11d8e72e80bf06c939f51e30e9318348e356012ae93802623e7e7460999b3f7e8ba755c0d29599ae788f4544e2d8c77419f7d87eed449b7d6813e006fe13f540d0d66182fef8c50ebd9d211e40be206647f7e00fd685b86946fa705ad4651c18ab2a320b4a69699ab0980126725a179cb3c64faa8f2509c4dddd4adebe64d5cd4207643b74cb951ade33149cd6cd51d669bce78e7df026fe1abb945332d7c0a9e2f0c8bc51b46617f418a10ed53af1ad8a5de091ee7b9161a36c5a28454693301b254151eaad572fe3718480827cbcb2b29cbbe2dd52029dfad21eac08db5c648820175597abb4a0c5ff69693595d1d3fe51de4c4f9c4194b77a63e7b407560fa73f56328d3cbee56843f26b4272acb3eeeaa0e46d0184c4df4adb62aec6770ccb2861933b80362d81b2e5010a91d2c8f139b9eb004455057809151ad7f7ca7b6b37b48037dfaf87a9f1e3fd2e3e9fbcddefded0a9ffe4050860aaf8120a12909a51025f739ff300c37edce140a5b599c11a069c8d6716e7a198692712ae072cb0833533e07f38919c92312fb2f264239dc7ee606385a6f34772835d1e53de7cab5f35053a3c24486db2f6f061efb91dd54dbb6f7b7acb00bb2002d390eee61b94c5e4bcc9b0317177adb53e6fc797830898cc53c48bbcce3f80100cbcd489454ce64ecdd98984531a7dc6f0ef02d73406eda7728fd6</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-wave">      <input class="hbe hbe-input-field hbe-input-field-wave" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-wave" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-wave">输入密码查看内容</span>      </label>      <svg class="hbe hbe-graphic hbe-graphic-wave" width="300%" height="100%" viewBox="0 0 1200 60" preserveAspectRatio="none">        <path d="M0,56.5c0,0,298.666,0,399.333,0C448.336,56.5,513.994,46,597,46c77.327,0,135,10.5,200.999,10.5c95.996,0,402.001,0,402.001,0"></path>      </svg>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">文章加密了，需要输入密码查看</summary>
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
    <category term="vue" scheme="https://sudo.rm-rf.ink/tags/vue/"/>
    
    <category term="表单" scheme="https://sudo.rm-rf.ink/tags/%E8%A1%A8%E5%8D%95/"/>
    
    <category term="formily" scheme="https://sudo.rm-rf.ink/tags/formily/"/>
    
  </entry>
  
  <entry>
    <title>成本核算</title>
    <link href="https://sudo.rm-rf.ink/*/fb428c48.html"/>
    <id>https://sudo.rm-rf.ink/*/fb428c48.html</id>
    <published>2024-01-25T07:09:54.000Z</published>
    <updated>2024-01-25T09:51:10.596Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="糟糕！密码错误了." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="44fc6b09e12b1dca25586a84cbdcad59fe5874ff258d27b23671866eb31f64cc">89730641517f40fad9fb11d8e72e80bf06c939f51e30e9318348e356012ae93802623e7e7460999b3f7e8ba755c0d29599ae788f4544e2d8c77419f7d87eed449b7d6813e006fe13f540d0d66182fef8c50ebd9d211e40be206647f7e00fd685b86946fa705ad4651c18ab2a320b4a69699ab0980126725a179cb3c64faa8f2509c4dddd4adebe64d5cd4207643b74cb951ade33149cd6cd51d669bce78e7df026fe1abb945332d7c0a9e2f0c8bc51b46617f418a10ed53af1ad8a5de091ee7b9161a36c5a28454693301b254151eaad572fe3718480827cbcb2b29cbbe2dd52029dfad21eac08db5c648820175597abb4a0c5ff69693595d1d3fe51de4c4f9c4194b77a63e7b407560fa73f56328d3cbee56843f26b4272acb3eeeaa0e46d0195048f25efe9b21ce963d68bba31f68109d09d5e9a4798ba30c885f456814a1f79a3813597deaa347db33459cd74ba7a0df0f4961b35961cf13b305d52d09764798e16bc3970b56199d955ddc1cc9c04c353fb965ceadfc5376a7704a76f05c3da2895c2e503e0f9acd812b0bc56d7b3677b1a7366b54e384df56d66b32e47484884bf3ad6f10f3899fa6a1d0ebc8f4a8f15a25926c5f09faafa892771e672dce8e9193fa9821d44cf076aab160fdd0005724034d18e4ec566a57f74d507df6d98454bbb420fcada5e86fac9dbfa97eeb919651443dcdc350dc638e6283d9e889b5ef81fbdf4f010db814ea35ae2d88b145fddbb9a4ec5fb960e01b8dccc33d9d1472271d360d47d559c2cd5ae29072cf1682091e200aaa447262efc45994d84b2c885e9b76e9f6b3ef00b89976974fb39dc4bdf102c62aba6f4d39dd48aa679f191b17b8ff5f2e0abcd9bd1f2337ad24b07c79ad4db23273f4d9b18e4413df745c0f31919fcc98d3b2a2ff051813176fcb8d58ee7f78dc47725baf6037a8c9c9023cd0664a14ad3df32b1860769e27cfc62a526a7429fc8a9bfa8f0c4eaf21b91b43f495b19552fc3cd3ba2059a4b27288ebba98589861a37f28b9e654f66021082d4c872a88d3facc4a920fd93fbe53794151d3810e0f41ae6ef736202eddf98d357b518c8ee5d24291815099bce81bbd1e3d5be21a6190e11110ebcebc495f364fb7ddd71af01062f3f4331541424ae155572f54b5b1a9e2a4451b7e5a67dc4ae23b02e2bcf8c5405caf52af747361a7e201552703e9e68652e283e243ae778b4fb061e2fe1c5a88b32885fa001c124fa4dbdf27e6dc8717891c8924f961a8d014b440cf0fee0804db043bdcf8004e56c8c9676c2bc925216219597ea804477986a7300a40bcc2a29f11ddfc2a7009402895b472b4d9abf359728dfa7fb1c32e3c396848fb0756c2c6d199f32eb1a953f75159e59b96a5d03d0b25032df570ad289c5da97f1e91fcc79f3132a357fbea1c0585c60b8ced01aa77f53cae07e61e0b01aa3b298aedf9c289ec3f1a8894d5947b2dd4a9790bc417c2fc4fcd46bb38325ad6aca04cf8d969c071d6758837d5e3da1e0708a6fa00fb64ce344ccc5631f40bd3713b7836a6855fd204c3448f21c8523ab9eeb094c7d504fa6dff88478d3e276817712a96f91c3269f5aa04cdf1bb4751a51a64f67bd2782535970e6bd38533bd3e89f41bf230062696042f6be90a95431374bac8d16bde9a58befbd3e2c60144bce8a3cc7fee5217def52301b310c0cfefbc8a1af62f6870a955daecf988ae609d847725cc6d0feccaa6e3142d82eef1ee24fdac8d752f719cf9c2023212e6df6c84f637f43757b7987545e8931c3da36550ec78b3f84e699703d6a72bf242b0da37f109dfe4ce60a5ad452dd3af59a631ecaca57f6ba537627d472300fad6925ff147fc94dc0be104fbfd6a49876ccbb3337af154ecc4e1788fea413e4dccb4049d2dc6010d28135ddca3d954c3668b8cf8dbf563fcdb86efda4822909ab8f17419a4ef3060cdcace08ef372da7a9d2314b1df1b56c8941debc6751d36ac4d8e7f6bc38a5ea7efd036094f137ef5041f35e1df174e62a4e9b85168c98c373cd32ecb6a085e39d243cfd3db5adf7bc0cca77d676cd9ea6cf8b1107a809dacfd8f51cd0b650a165c608439c0f1400e991fb804334832ef4b0220273cc27212101228cb0da9474d977766514151b13a02dfcec92437399a2b7e4d0864d8030d776bcb4b81034fb5eb2c04bbc0fa62ea6b79f119f779efdcdc8442c70894338dc66320290eb56ff022ed0c34906f20705ce50d2b79450d001c79757e3c833de3db9226d052a38b781b149feb66773de072bc2fd8c3782f6ceda0ece7cb0681b977ee13faaf85d92444b052f0bc1295a6415aa25580cc540b96c3117c6270e8f7c43e65564284c38a607c616f7994e40283079c04b11aac4ffec23bc26753cb32ec18bdffa12709caafec6291fe7964cb6600f9034705b0cc8170f11c3c7e4e4d0e2eb0b2a04dd514da1b3779951bd6dc5588e768caccc5a81c91cab48d28a89468d3ddad9325afdb5bba58e8670f7244606e0d4a79bfdcc6ff94d06ba7af6cde978c9bd64a5e3e30534794bc63c5c42c055936e84b687dd1a6d82f2e58eb760f9c422ee12be872c6a01b043cb2bda28791eb038b87a01c17015db6a112442934e9b93e8ddd90738b8fe725487e88fb58bffe09dd659cd1a3e11939fa78e18d08fea534f0b2f997530236867e8b78e91aeb30452f29361da203b20e06b247bfc22243c7f8f42b93722578b2f8f10dc9c638e2799024feb319a2010a212d3c891ef1a555820e3d0be66d224112c010488de485babf31216505e4199078aabe5c50273c3aa07fd19c65351009103594858553d400fea8e7f291b49b1714effbfc41940f6a0c72e9b06f0b4ddb8be951974c86bcae83f74a7c59bd924dd00c5494fc5c7cc6a0636d96e32bd220be55371e3a500300d1653a24e7fa9ce55bed09b3464a1e8007b4023a645d69c07784ed307b37e40cd34b34c406d9e2f7ac9054241c4f56af824156bf38b4fe19d6730dab1615532654db2642079c989876c5b4ee7ad737cde310b4f3b286b5485e542a5e51e1d27e4dde347482dd81c2e31cee68101262974f9853e250c1e7d0e997f267af4d20f757ea784bec6f205250934bad7fa43a691a2b128eaa0accc2c7f4dbf9a6e3119670587607ef555a3ffd3ecb5132a2dceb93f7d30d72cb69423ba21d3b665213c9152eabaf9fe0959749d942c6d2312254a197c21fe32a2bfe23889dcfd251b5e91ae2e2a57c3f79a33d8efc35015bad567838f453f1c1e43dd73bf51480d60923cbb7a54dc1b939fea28d05f8de237866ce74ed2c0a19a4643fca17010805b698a21858a1f872d1002ef9a30c73dae2ecf691469cd92931b9fe98</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-wave">      <input class="hbe hbe-input-field hbe-input-field-wave" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-wave" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-wave">输入密码查看内容</span>      </label>      <svg class="hbe hbe-graphic hbe-graphic-wave" width="300%" height="100%" viewBox="0 0 1200 60" preserveAspectRatio="none">        <path d="M0,56.5c0,0,298.666,0,399.333,0C448.336,56.5,513.994,46,597,46c77.327,0,135,10.5,200.999,10.5c95.996,0,402.001,0,402.001,0"></path>      </svg>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">文章加密了，需要输入密码查看</summary>
    
    
    
    <category term="工作" scheme="https://sudo.rm-rf.ink/categories/%E5%B7%A5%E4%BD%9C/"/>
    
    
  </entry>
  
  <entry>
    <title>奇怪的梦</title>
    <link href="https://sudo.rm-rf.ink/*/2afb063d.html"/>
    <id>https://sudo.rm-rf.ink/*/2afb063d.html</id>
    <published>2024-01-25T02:09:11.000Z</published>
    <updated>2024-02-05T07:53:52.538Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="糟糕！密码错误了." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="0a751ab2cab789f89ab563c1df7773ac753b4ac0f92147c2c3b943ed66d2bbde">89730641517f40fad9fb11d8e72e80bf06c939f51e30e9318348e356012ae93802623e7e7460999b3f7e8ba755c0d29599ae788f4544e2d8c77419f7d87eed449b7d6813e006fe13f540d0d66182fef8c50ebd9d211e40be206647f7e00fd685b86946fa705ad4651c18ab2a320b4a69699ab0980126725a179cb3c64faa8f2509c4dddd4adebe64d5cd4207643b74cb951ade33149cd6cd51d669bce78e7df026fe1abb945332d7c0a9e2f0c8bc51b46617f418a10ed53af1ad8a5de091ee7b9161a36c5a28454693301b254151eaad572fe3718480827cbcb2b29cbbe2dd52029dfad21eac08db5c648820175597abb4a0c5ff69693595d1d3fe51de4c4f9c4194b77a63e7b407560fa73f56328d3cbee56843f26b4272acb3eeeaa0e46d01101c2c8c781e0b1cd8c2268fc4efcf73eca9ec52ed737c3e4b1fc88ab5677a7f6b2a62a2e14f94a5baf9c3196a1aa8cb0da095c4d0a4032935d7df8bfad0a2f3b9b456191eff772b024a0d4a32d85d8f8524dec24a9148950127e2adbd9a26578ed16c252bf25c35426dd6517a40c5926e1c6cb8e8294e15ca5801107d94b580ec386c3f00be8540f1b49668ebacc077b6f3336c569dec0e085e833399f37688fd7b3c47f3e1e8de882e4b6d5cd64ac86338f967fc35d1d4eea06035b826eabe2263698ba13b225d97d2c771bb4de617fbafd3c0ffdae4e1e5d3ac1b8ff8491459ea01b954978e52bb44a32630d794663cfc88878f79a6bacc313b01a3e51978bf4e192b35648c90677ab09dfb00fc6d631338b2548542f4858da83e9228d11046a4a1c7726c45eb62eae142e6cb91a36b39470de9bdf2b4e3cd34c2bb3877418d5917305a89b60398ec3dc1e825a69c38ea2a836766665c449052b4c1a682e0f73f068cfbfc28df6cc44b83779e372403309ebbf7ed049e5737817025d9a295ffa9c27673cf2ecc30a20288465b51963d3d0a46d1142ae2a039664f06c2d95e9624899b2987d27754d20a494f7d36c0</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-wave">      <input class="hbe hbe-input-field hbe-input-field-wave" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-wave" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-wave">输入密码查看内容</span>      </label>      <svg class="hbe hbe-graphic hbe-graphic-wave" width="300%" height="100%" viewBox="0 0 1200 60" preserveAspectRatio="none">        <path d="M0,56.5c0,0,298.666,0,399.333,0C448.336,56.5,513.994,46,597,46c77.327,0,135,10.5,200.999,10.5c95.996,0,402.001,0,402.001,0"></path>      </svg>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">文章加密了，需要输入密码查看</summary>
    
    
    
    <category term="生活" scheme="https://sudo.rm-rf.ink/categories/%E7%94%9F%E6%B4%BB/"/>
    
    
    <category term="奇怪" scheme="https://sudo.rm-rf.ink/tags/%E5%A5%87%E6%80%AA/"/>
    
    <category term="梦" scheme="https://sudo.rm-rf.ink/tags/%E6%A2%A6/"/>
    
  </entry>
  
  <entry>
    <title>revealjs-animated动画文档</title>
    <link href="https://sudo.rm-rf.ink/*/8212ba91.html"/>
    <id>https://sudo.rm-rf.ink/*/8212ba91.html</id>
    <published>2024-01-24T10:00:16.000Z</published>
    <updated>2024-01-25T01:53:21.591Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="/assets/css/APlayer.min.css"><script src="/assets/js/APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="/assets/js/Meting.min.js"></script><p><a href="https://rogeralmeida.github.io/revealjs-animated-examples/">查看示例</a></p><h2 id="如何安装"><a class="markdownIt-Anchor" href="#如何安装"></a> 如何安装</h2><ol><li class="lvl-3"><p>安装revealjs-animated插件</p></li></ol><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">npm install revealjs-animated</span><br></pre></td></tr></table></figure><ol start="2"><li class="lvl-3"><p>在Reveal.js中初始化安装路径</p></li></ol><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//index.html</span></span><br><span class="line"><span class="title class_">Reveal</span>.<span class="title function_">initialize</span>(&#123;</span><br><span class="line">    <span class="attr">dependencies</span>: [</span><br><span class="line">        <span class="comment">// Other plugins</span></span><br><span class="line">        &#123;<span class="attr">src</span>: <span class="string">&#x27;node_modules/revealjs-animated/dist/revealjs-animated.js&#x27;</span>, <span class="attr">async</span>: <span class="literal">true</span>&#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h2 id="如何使用"><a class="markdownIt-Anchor" href="#如何使用"></a> 如何使用？</h2><h3 id="居中移动动画"><a class="markdownIt-Anchor" href="#居中移动动画"></a> 居中移动动画</h3><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!--html--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">id</span>=<span class="string">&quot;titulo&quot;</span> <span class="attr">class</span>=<span class="string">&quot;fragment animated move-to-middle-top&quot;</span>&gt;</span>居中<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--md--&gt;</span></span><br><span class="line"># 居中<span class="comment">&lt;!-- .element: class=&quot;fragment animated move-to-middle-top&quot; --&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="属性"><a class="markdownIt-Anchor" href="#属性"></a> 属性</h4><p>此动画不允许使用任何属性。</p><h3 id="自定义位置移动动画"><a class="markdownIt-Anchor" href="#自定义位置移动动画"></a> 自定义位置移动动画</h3><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!--html--&gt;</span>    </span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;fragment animated move-to&quot;</span>&gt;</span>默认参数<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--md--&gt;</span></span><br><span class="line">默认参数<span class="comment">&lt;!-- .element: class=&quot;fragment animated move-to&quot; --&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="属性-2"><a class="markdownIt-Anchor" href="#属性-2"></a> 属性</h4><table><thead><tr><th>名称</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td>data-animated-move-to-left</td><td>50px</td><td>动画对象应在X轴上移动的距离</td></tr><tr><td>data-animated-move-to-top</td><td>25px</td><td>动画对象应在Y轴上移动的距离</td></tr></tbody></table><h3 id="放大动画"><a class="markdownIt-Anchor" href="#放大动画"></a> 放大动画</h3><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!--html--&gt;</span>    </span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;fragment animated scale-up&quot;</span>&gt;</span>放大<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--md--&gt;</span></span><br><span class="line">放大<span class="comment">&lt;!-- .element: class=&quot;fragment animated scale-up&quot; --&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="属性-3"><a class="markdownIt-Anchor" href="#属性-3"></a> 属性</h4><table><thead><tr><th>名称</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td>data-animated-scale-up-from</td><td>1</td><td>起始值</td></tr><tr><td>data-animated-scale-up-to</td><td>2</td><td>最大值</td></tr></tbody></table><h3 id="缩小动画"><a class="markdownIt-Anchor" href="#缩小动画"></a> 缩小动画</h3><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!--html--&gt;</span>    </span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;fragment animated scale-down&quot;</span>&gt;</span>缩小<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--md--&gt;</span></span><br><span class="line">缩小<span class="comment">&lt;!-- .element: class=&quot;fragment animated scale-down&quot; --&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="属性-4"><a class="markdownIt-Anchor" href="#属性-4"></a> 属性</h4><table><thead><tr><th>名称</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td>data-animated-scale-down-from</td><td>1</td><td>起始值</td></tr><tr><td>data-animated-scale-down-to</td><td>0.5</td><td>最小值</td></tr></tbody></table><h3 id="旋转动画"><a class="markdownIt-Anchor" href="#旋转动画"></a> 旋转动画</h3><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!--html--&gt;</span>    </span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;fragment animated rotate&quot;</span>&gt;</span>旋转<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--md--&gt;</span></span><br><span class="line">旋转<span class="comment">&lt;!-- .element: class=&quot;fragment animated rotate&quot; --&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="属性-5"><a class="markdownIt-Anchor" href="#属性-5"></a> 属性</h4><table><thead><tr><th>名称</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td>data-animated-rotate-from</td><td><code>0deg</code></td><td>起始角度</td></tr><tr><td>data-animated-rotate-to</td><td><code>180deg</code></td><td>最大角度</td></tr></tbody></table><h2 id="时间属性"><a class="markdownIt-Anchor" href="#时间属性"></a> 时间属性</h2><p><code>duration</code>, <code>iteration</code> 和 <code>fill</code> 动画属性可以通过以下属性进行控制：</p><h4 id="属性-6"><a class="markdownIt-Anchor" href="#属性-6"></a> 属性</h4><table><thead><tr><th>名称</th><th>必填</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td>data-animated-duration</td><td>否</td><td>1000</td><td>动画持续时间(毫秒)</td></tr><tr><td>data-animated-iterations</td><td>否</td><td>1</td><td>动画循环次数</td></tr><tr><td>data-animated-fill</td><td>否</td><td>forwards</td><td>动画最终状态 <code>forwards</code>, <code>none</code>, <code>backwards</code>, <code>both</code>, <code>auto</code>. 更多属性设置 <a href="https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/fill">MDN: EffectTiming.fill</a></td></tr></tbody></table><h1 id="组合动画"><a class="markdownIt-Anchor" href="#组合动画"></a> 组合动画</h1><p>从1.2.0版本开始，可以将多个动画组合在一起以创建动画。只需要添加多个CSS类。</p><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!--html--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;fragment animated move-to-middle-top rotate&quot;</span>&gt;</span>移动并旋转<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--md--&gt;</span></span><br><span class="line">移动并旋转<span class="comment">&lt;!-- .element: class=&quot;fragment animated  move-to-middle-top rotate&quot; --&gt;</span></span><br></pre></td></tr></table></figure><p><a href="#general-time-attributes">时间属性</a> 只能用于组合动画，不能单独用于每个动画；</p>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;/assets/css/APlayer.min.css&quot;&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot; cla</summary>
      
    
    
    
    <category term="学习" scheme="https://sudo.rm-rf.ink/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="reveal.js" scheme="https://sudo.rm-rf.ink/tags/reveal-js/"/>
    
    <category term="animate" scheme="https://sudo.rm-rf.ink/tags/animate/"/>
    
    <category term="css动画" scheme="https://sudo.rm-rf.ink/tags/css%E5%8A%A8%E7%94%BB/"/>
    
    <category term="css" scheme="https://sudo.rm-rf.ink/tags/css/"/>
    
  </entry>
  
</feed>
