<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>开发 on erpan&#39;s note</title>
    <link>https://940504.top/categories/%E5%BC%80%E5%8F%91/</link>
    <description>Recent content in 开发 on erpan&#39;s note</description>
    <image>
      <title>erpan&#39;s note</title>
      <url>https://940504.top/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</url>
      <link>https://940504.top/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</link>
    </image>
    <generator>Hugo -- 0.154.5</generator>
    <language>en</language>
    <copyright>浙ICP备2021018236号-1</copyright>
    <lastBuildDate>Fri, 06 Feb 2026 18:50:00 +0800</lastBuildDate>
    <atom:link href="https://940504.top/categories/%E5%BC%80%E5%8F%91/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>AI Agent编排范式</title>
      <link>https://940504.top/posts/ai-agent%E7%BC%96%E6%8E%92%E8%8C%83%E5%BC%8F/</link>
      <pubDate>Fri, 06 Feb 2026 18:50:00 +0800</pubDate>
      <guid>https://940504.top/posts/ai-agent%E7%BC%96%E6%8E%92%E8%8C%83%E5%BC%8F/</guid>
      <description>&lt;h1 id=&#34;ai-agent编排范式&#34;&gt;AI Agent编排范式&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;范式主要整理自Eino框架，文中有些概念仅属于Eino框架&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;引言&#34;&gt;引言&lt;/h2&gt;
&lt;p&gt;AI应用的核心任务极为简单：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;接收指令&lt;/li&gt;
&lt;li&gt;调用大模型&lt;/li&gt;
&lt;li&gt;安全地执行工具（运行命令、操作文件、控制浏览器）&lt;/li&gt;
&lt;li&gt;之后将结果反馈给你&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;三个关键原则，是解决一切花哨问题的基础：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;执行是能控制的&lt;/li&gt;
&lt;li&gt;状态是能追溯的&lt;/li&gt;
&lt;li&gt;失败是能复盘的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI应用的核心任务，即ReAct模式，通过让 ChatModel 进行显式的、一步一步的&amp;quot;思考&amp;quot;来解决复杂问题，在Eino ADK中将其直接抽象为ChatModelAgent了。在不同的领域、不同的场景下有各种各样的模型，也有各种各样的Agent来处理专有领域的任务，如Coding模型、视觉模型等。一个复杂的任务通常需要调用各种能力的模型和各种工具来完成任务，这就需要把这些拥有专有能力的Agent编排起来组成一个功能完善、强大的应用。&lt;/p&gt;
&lt;h2 id=&#34;ai-agent编排范式分类&#34;&gt;AI Agent编排范式分类&lt;/h2&gt;
&lt;p&gt;AI Agent编排范式大概分为以下几类：&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    mindmap
  root((AI Agent编排范式))
    Eino框架原生范式
      基础编排层
        Chain链式编排: Graph的封装，除了 &amp;#34;环&amp;#34; 之外，Chain 暴露了几乎所有 Graph 的能力。线性单向流/简单任务
        Graph图编排: 支持pregel和dag模式/分支/并行/循环/复杂逻辑
        Workflow工作流编排: DAG模式，字段级别映射，控制流/数据流分离
        图嵌套：Eino中的chain、graph、workflow都可以嵌套进图
      Agent编排
        ChatModelAgent: 智能决策大脑，实现ReAct模式，LLM交互核心
        Workflow Agents: 流程协调
          Sequential Agent: 串行执行按顺序流转，如CI/CD流水线，数据ETL
          Parallel Agent: 并行执行/共享输入/结果聚合，如多源数据采集、多渠道推送
          Loop Agent: 循环执行/结果积累/条件退出，数据同步、压力测试
        Custom Agent: 可高度定制
      预构建Multi-Agent
        Plan-Execute Agent: 规划-执行-重规划，结构化解决复杂任务，如复杂任务研究，智能助理任务执行
        Supervisor Agent: 监督者统筹/子Agent分工/汇总决策
        DeepAgents: 规划驱动集中协作，强化拆解与上下文隔离
        
    通用行业主流范式
      经典协作模式
        Master-Slave（主从）: 主Agent分配任务/从Agent执行/无自主决策
        Swarm（蜂群）: 无中心/Agent自主协作/去中心化/高容错
        Hierarchical（层级）: 多层级Agent/上层决策/下层执行/复杂系统
        Peer-to-Peer（对等）: 平级Agent/自主协商/资源共享/无核心节点
&lt;/pre&gt;
&lt;h2 id=&#34;详细编排范式解析&#34;&gt;详细编排范式解析&lt;/h2&gt;
&lt;h3 id=&#34;1-基础编排层&#34;&gt;1. 基础编排层&lt;/h3&gt;
&lt;h4 id=&#34;chain链式编排&#34;&gt;Chain（链式编排）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: Graph的封装，除了&amp;quot;环&amp;quot;之外，Chain暴露了几乎所有Graph的能力，适用于线性单向流/简单任务&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;数据处理流水线（如ETL过程）&lt;/li&gt;
&lt;li&gt;顺序执行的任务链&lt;/li&gt;
&lt;li&gt;简单的工作流程&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;graph图编排&#34;&gt;Graph（图编排）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 支持Pregel和DAG模式，能够处理分支、并行、循环等复杂逻辑&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;复杂业务逻辑处理&lt;/li&gt;
&lt;li&gt;需要条件分支和循环的任务&lt;/li&gt;
&lt;li&gt;并行计算任务&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;workflow工作流编排&#34;&gt;Workflow（工作流编排）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: DAG模式，不支持环，支持字段级别映射，强调控制流和数据流分离&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;数据集成和转换&lt;/li&gt;
&lt;li&gt;需要精确字段映射的场景&lt;/li&gt;
&lt;li&gt;复杂的数据处理管道&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;2-agent编排层&#34;&gt;2. Agent编排层&lt;/h3&gt;
&lt;h4 id=&#34;chatmodelagent&#34;&gt;ChatModelAgent&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 智能决策大脑，实现ReAct模式，是LLM交互核心&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;需要推理和决策的场景&lt;/li&gt;
&lt;li&gt;自然语言交互&lt;/li&gt;
&lt;li&gt;复杂问题分解&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;workflow-agents&#34;&gt;Workflow Agents&lt;/h4&gt;
&lt;h5 id=&#34;sequential-agent&#34;&gt;Sequential Agent&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 串行执行按顺序流转&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;研究报告撰写流程&lt;/li&gt;
&lt;li&gt;CI/CD流水线&lt;/li&gt;
&lt;li&gt;数据提取、转换和加载(ETL)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    flowchart LR
  subgraph one[Sequential Agent]
    PlanAgent[Plan Agent&amp;lt;br/&amp;gt;制定研究计划] --&amp;gt; WriteAgent[Write Agent&amp;lt;br/&amp;gt;撰写学术报告]
  end
    Start[开始研究主题] --&amp;gt; one
    one --&amp;gt; End[结束]
&lt;/pre&gt;
&lt;h5 id=&#34;parallel-agent&#34;&gt;Parallel Agent&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 并行执行/共享输入/结果聚合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;多源数据采集&lt;/li&gt;
&lt;li&gt;并行数据分析&lt;/li&gt;
&lt;li&gt;多渠道信息收集&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    flowchart LR
  subgraph p[彼此之间无需交互，功能边界清晰]
    a[Stock Data Collection Agent&amp;lt;br/&amp;gt;股票数据采集]
    b[News Data Collection Agent&amp;lt;br/&amp;gt;新闻数据采集]
    c[Social Media Info Collection Agent&amp;lt;br/&amp;gt;社媒信息采集]
    d[聚合]
  end
    Start[开始] --&amp;gt; a
    Start --&amp;gt; b
    Start --&amp;gt; c
    a --&amp;gt; d
    b --&amp;gt; d
    c --&amp;gt; d
    d --&amp;gt; End[结束]
&lt;/pre&gt;
&lt;h5 id=&#34;loop-agent&#34;&gt;Loop Agent&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 循环执行/结果积累/条件退出&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;解决方案优化迭代&lt;/li&gt;
&lt;li&gt;数据同步、压力测试&lt;/li&gt;
&lt;li&gt;反馈循环改进&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    flowchart LR
  subgraph loop[反思迭代]
    a[Main Agent&amp;lt;br/&amp;gt;生成初步解决方案] --&amp;gt; b[Critique Agent&amp;lt;br/&amp;gt;质量审查/反馈改进]
    b --&amp;gt;|结果不满意&amp;lt;br/&amp;gt;MaxIteration=5| a
  end
    Start[开始] --&amp;gt; loop
    loop --&amp;gt;|结果满足| End[结束]
&lt;/pre&gt;
&lt;h3 id=&#34;3-预构建multi-agent范式&#34;&gt;3. 预构建Multi-Agent范式&lt;/h3&gt;
&lt;h4 id=&#34;plan-execute-agent&#34;&gt;Plan-Execute Agent&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 规划-执行-重规划，适合需要多步骤推理、动态调整和工具集成的复杂任务场景&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;复杂研究任务&lt;/li&gt;
&lt;li&gt;需要多步规划的项目&lt;/li&gt;
&lt;li&gt;动态任务调整&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    flowchart TD
    A[1. UserInput] --&amp;gt; B[Planner]
    B --&amp;gt;|2. 生成具体的计划步骤| C[Plan Steps&amp;lt;br/&amp;gt;1. ...&amp;lt;br/&amp;gt;2. ...&amp;lt;br/&amp;gt;3. ...]
    C --&amp;gt;|3. 执行计划的第一步| D[Executor]
    D --&amp;gt;|4. 传达当前的计划和第一步运行的结果| E[Replanner]
    E --&amp;gt;|5a. 评估并生成已调整的新计划&amp;lt;br/&amp;gt;交给Executor执行新计划的第一步| D
    E --&amp;gt;|5b. 评估任务执行的完成情况&amp;lt;br/&amp;gt;或达到最大迭代次数| F[End]
&lt;/pre&gt;
&lt;h4 id=&#34;supervisor-agent&#34;&gt;Supervisor Agent&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 监督者统筹/子Agent分工/汇总决策&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;多Agent任务分配和管理&lt;/li&gt;
&lt;li&gt;动态任务路由&lt;/li&gt;
&lt;li&gt;Agent间的协调&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    flowchart LR
        subgraph subagents
                a[Agent1]
                b[Agent2]
                c[Agent3]
        end

        s[Supervisor Agent] &amp;lt;--&amp;gt; |dispatch mission&amp;lt;/br&amp;gt;return result| a
        s &amp;lt;--&amp;gt; |dispatch mission&amp;lt;/br&amp;gt;return result| b
        s &amp;lt;--&amp;gt; |dispatch mission&amp;lt;/br&amp;gt;return result| c
        s --&amp;gt; Exit
&lt;/pre&gt;
&lt;h4 id=&#34;layered-supervisor&#34;&gt;Layered-Supervisor&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;: 多层级任务管理和动态路由&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    flowchart LR
    TopSupervisor[Supervisor Agent&amp;lt;br/&amp;gt;顶层监督者-动态路由] --&amp;gt; Research[Research Agent&amp;lt;br/&amp;gt;信息检索]
    TopSupervisor --&amp;gt; MathSuper[Math Agent&amp;lt;br/&amp;gt;中层监督者-数学运算]
    MathSuper --&amp;gt; Subtract[Subtract Agent&amp;lt;br/&amp;gt;减法运算]
    MathSuper --&amp;gt; Multiply[Multiply Agent&amp;lt;br/&amp;gt;乘法运算]
    MathSuper --&amp;gt; Divide[Divide Agent&amp;lt;br/&amp;gt;除法运算]
&lt;/pre&gt;
&lt;h4 id=&#34;deepagents&#34;&gt;DeepAgents&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;：规划驱动的集中式协作，Main Agent 统一协调下的 Multi-Agent 模式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流程&lt;/strong&gt;：
&lt;ol&gt;
&lt;li&gt;通过 WriteTodos 将用户目标拆解为结构化待办并记录进度&lt;/li&gt;
&lt;li&gt;通过统一入口 TaskTool 选择并调用对应的 SubAgent 执行子任务；主/子代理上下文隔离，避免中间步骤污染主流程。&lt;/li&gt;
&lt;li&gt;汇总各子代理返回的结果；必要时再次调用 WriteTodos 更新进度或进行重规划，直至完成。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;多角色协作的复杂业务流程，集中委派子任务并统一汇总&lt;/li&gt;
&lt;li&gt;严格上下文隔离的执行环境&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
    flowchart TD
    subgraph MainAgent
        ChatModel[ChatModel]
        subgraph Tools
            WriteTodos[WriteTodos]
            TaskTool[TaskTool]
            CustomTools[CustomTools]
        end
    end
    subgraph SubAgents
            GeneralPurpose[GeneralPurpose]
            CustomSubAgents[CustomSubAgents]
        end

    ChatModel --&amp;gt;|Reasoning &amp;amp; Action| Tools
    Tools --&amp;gt; ChatModel

    TaskTool --&amp;gt;|Delegate Tasks| SubAgents
    SubAgents --&amp;gt;|Return Results| TaskTool
&lt;/pre&gt;
&lt;h3 id=&#34;4-其他主流范式&#34;&gt;4. 其他主流范式&lt;/h3&gt;
&lt;h4 id=&#34;master-slave主从模式&#34;&gt;Master-Slave（主从模式）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 主Agent分配任务/从Agent执行/无自主决策&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;任务分配明确的系统&lt;/li&gt;
&lt;li&gt;标准化执行任务&lt;/li&gt;
&lt;li&gt;控制权集中的场景&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;swarm蜂群模式&#34;&gt;Swarm（蜂群模式）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 无中心/Agent自主协作/去中心化/高容错&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;去中心化系统&lt;/li&gt;
&lt;li&gt;高容错需求&lt;/li&gt;
&lt;li&gt;自适应环境&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;hierarchical层级模式&#34;&gt;Hierarchical（层级模式）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 多层级Agent/上层决策/下层执行/复杂系统&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;大型复杂系统&lt;/li&gt;
&lt;li&gt;分层决策机制&lt;/li&gt;
&lt;li&gt;组织化任务分配&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;peer-to-peer对等模式&#34;&gt;Peer-to-Peer（对等模式）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定义&lt;/strong&gt;: 平级Agent/自主协商/资源共享/无核心节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;平等协作环境&lt;/li&gt;
&lt;li&gt;资源共享&lt;/li&gt;
&lt;li&gt;无单点故障需求&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;选择编排范式&#34;&gt;选择编排范式&lt;/h2&gt;
&lt;h3 id=&#34;任务复杂度&#34;&gt;任务复杂度&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;简单 → Chain/Sequential&lt;/li&gt;
&lt;li&gt;中等 → Graph/Workflow&lt;/li&gt;
&lt;li&gt;复杂 → Plan-Execute/Supervisor&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;执行模式&#34;&gt;执行模式&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;顺序 → Chain/Sequential&lt;/li&gt;
&lt;li&gt;并行 → Parallel&lt;/li&gt;
&lt;li&gt;迭代 → Loop&lt;/li&gt;
&lt;li&gt;动态调整 → Plan-Execute&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;AI Agent编排范式的选择需要根据具体的应用场景、任务复杂度和系统需求进行综合考虑。无论选择哪种范式，都需要遵循&amp;quot;执行可控、状态可追溯、失败可复盘&amp;quot;的原则，确保系统的稳定性和可维护性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>基于Eino框架理解大模型工具调用</title>
      <link>https://940504.top/posts/%E5%9F%BA%E4%BA%8Eeino%E6%A1%86%E6%9E%B6%E7%90%86%E8%A7%A3%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%B7%A5%E5%85%B7%E8%B0%83%E7%94%A8/</link>
      <pubDate>Fri, 18 Apr 2025 20:19:19 +0800</pubDate>
      <guid>https://940504.top/posts/%E5%9F%BA%E4%BA%8Eeino%E6%A1%86%E6%9E%B6%E7%90%86%E8%A7%A3%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%B7%A5%E5%85%B7%E8%B0%83%E7%94%A8/</guid>
      <description>&lt;h2 id=&#34;函数调用-function-calling&#34;&gt;函数调用 Function Calling&lt;/h2&gt;
&lt;p&gt;Function Calling 是一种将大模型与外部工具和 API 相连的关键功能，大模型能够将用户的自然语言智能地转化为对特定工具或 API 的调用，从而高效满足各种场景需求，如动态信息查询、任务自动化等&lt;/p&gt;
&lt;p&gt;工具调用的一般步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;应用程序将用户问题和tools列表一起发送给大模型，tools列表表明模型可以调用的工具&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LLM 对用户意图进行分析，决定是否需要使用工具以及使用哪些工具&lt;/p&gt;
&lt;p&gt;a. 无需工具则生成回答响应给应用程序&lt;/p&gt;
&lt;p&gt;b. 需要调用工具输出工具名和参数信息响应给应用程序&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;应用程序解析模型响应&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;有工具调用，则调用工具并将调用结果和之前的消息记录一并发给模型，继续处理&lt;/li&gt;
&lt;li&gt;无工具调用，继续处理程序逻辑或直接给用户&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;循环上面步骤，达到结束条件则会话完成&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;火山引擎文档中有一张图多轮工具调用的逻辑图，可以辅助理解  &lt;a href=&#34;https://www.volcengine.com/docs/82379/1262342#%E5%A4%9A%E8%BD%AE%E5%B7%A5%E5%85%B7%E8%B0%83%E7%94%A8&#34;&gt;多轮工具调用&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;mcp&#34;&gt;MCP&lt;/h2&gt;
&lt;p&gt;官网 &lt;a href=&#34;https://modelcontextprotocol.io/&#34;&gt;https://modelcontextprotocol.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;MCP（Model Context Protocol）即模型上下文协议，与 function calling（函数调用）都是实现大语言模型与外部系统交互的关键技术概念&lt;/p&gt;
&lt;p&gt;MCP 主要负责规范化函数的具体执行过程，为 AI 模型和外部数据源或工具之间建立统一的通信接口。&lt;/p&gt;
&lt;p&gt;二者的关系表现为 function calling 是 MCP 生态下的一种具体功能实现形式。function calling 为 MCP 提供了函数调用的指令来源，而 MCP 则为 function calling 生成的指令提供了标准化的执行框架，确保这些指令能够在不同的外部系统中可靠地执行。&lt;/p&gt;
&lt;p&gt;MCP也可以简单理解为function的共享，因此MCP开源社区在最近几个月都非常活跃。&lt;/p&gt;
&lt;p&gt;MCP遵循CS架构（Client-Server），几个核心概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;主机（Host）&lt;/strong&gt;：通常是发起连接的 LLM 应用程序，如 Claude Desktop、IDE 插件等，负责管理客户端实例和安全策略&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;客户端（Client）&lt;/strong&gt;：位于主机内，是主机与服务器之间的桥梁，与服务器建立 1:1 会话，处理协议协商和消息路由等&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务器（Server）&lt;/strong&gt;：是独立运行的轻量级服务，通过标准化接口提供特定功能，如文件系统访问、数据库查询等&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;核心架构这块参考官方文档 &lt;a href=&#34;https://modelcontextprotocol.io/docs/concepts/architecture&#34;&gt;https://modelcontextprotocol.io/docs/concepts/architecture&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;传输机制&#34;&gt;传输机制&lt;/h3&gt;
&lt;p&gt;MCP的client-server间传输层协议当前有两种，都使用JSON-RPC2.0作为消息交换格式：&lt;/p&gt;
&lt;h4 id=&#34;stdio&#34;&gt;&lt;em&gt;Stdio&lt;/em&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;进程间通信&lt;/li&gt;
&lt;li&gt;适用于命令行等同服务器通信&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Client将Server作为子进程启动，Server从其标准输入 （&lt;code&gt;stdin&lt;/code&gt;） 读取 JSON-RPC 消息，并将消息发送到其标准输出 （&lt;code&gt;stdout&lt;/code&gt;）。Server可以将 UTF-8 字符串写入其标准错误 （&lt;code&gt;stderr&lt;/code&gt;） 以进行日志记录，Client可以捕获、转发或忽略此日志记录。Server不能向其 &lt;code&gt;stdout&lt;/code&gt; 写入任何不是有效 MCP 消息的内容，Client不能向Server的 &lt;code&gt;stdin&lt;/code&gt; 写入任何不是有效 MCP 消息的内容。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Go 装饰器模式与洋葱模型</title>
      <link>https://940504.top/posts/go-%E8%A3%85%E9%A5%B0%E5%99%A8%E6%A8%A1%E5%BC%8F%E4%B8%8E%E6%B4%8B%E8%91%B1%E6%A8%A1%E5%9E%8B/</link>
      <pubDate>Thu, 18 Aug 2022 22:53:06 +0800</pubDate>
      <guid>https://940504.top/posts/go-%E8%A3%85%E9%A5%B0%E5%99%A8%E6%A8%A1%E5%BC%8F%E4%B8%8E%E6%B4%8B%E8%91%B1%E6%A8%A1%E5%9E%8B/</guid>
      <description>简要理解设计思路和用法</description>
    </item>
    <item>
      <title>golang context包用法理解</title>
      <link>https://940504.top/posts/golang-context%E5%8C%85%E7%90%86%E8%A7%A3/</link>
      <pubDate>Tue, 15 Feb 2022 20:13:06 +0800</pubDate>
      <guid>https://940504.top/posts/golang-context%E5%8C%85%E7%90%86%E8%A7%A3/</guid>
      <description>简要理解其用法</description>
    </item>
    <item>
      <title>client-go RingGrowingBuffer 环形缓冲区</title>
      <link>https://940504.top/posts/client-go%E4%B8%AD%E7%9A%84ringgrowingbuffer%E7%BC%93%E5%86%B2/</link>
      <pubDate>Mon, 11 Oct 2021 22:27:36 +0800</pubDate>
      <guid>https://940504.top/posts/client-go%E4%B8%AD%E7%9A%84ringgrowingbuffer%E7%BC%93%E5%86%B2/</guid>
      <description>&lt;p&gt;在client-go源码中，processorListener对象里面定义了一个RingBuffer用于缓存所有尚未分发的事件通知，在此记录下这个RingBuffer。&lt;/p&gt;
&lt;p&gt;RingBuffer一般用于数据的缓存机制，例如tcp协议里面数据包的缓冲就利用到了RingBuffer。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;client-go中的这个buffer是非线程安全、可增长、无边界的先进先出环形缓冲区&lt;/strong&gt;。环是一个逻辑上的概念，有了环，此段内存空间就可以重复利用，不用频繁重新申请内存，本质上数据还是存在数组里面的，这个数组的大小可以按需进行倍数扩容，扩容后需要重新分配内存空间并拷贝未消费的数据到新数组来。因为它是数组，内存是预先分配的，数组是内存上连续的一段空间，它有一个容易预测的访问模式，因此对CPU高速缓存友好，垃圾回收（GC）在这种情况下也不用做什么。&lt;br /&gt;
&lt;br /&gt;在实现上，可以理解为两个指针：a) 读指针、b)写指针。在一段buffer上，读指针控制下一次该读数据的位置，写指针控制下一次该写数据的位置。在数组里面我们可以直接用数组下标。要遵循FIFO原则，读指针不能超过写指针，两指针重叠了要么buffer写满了，要么buffer为空。&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;参考&lt;a href=&#34;https://en.wikipedia.org/wiki/Circular_buffer#/media/File:Circular_Buffer_Animation.gif&#34;&gt;这里的一张图&lt;/a&gt;
&lt;img alt=&#34;Circular_Buffer_Animation&#34; loading=&#34;lazy&#34; src=&#34;https://940504-1306126584.cos.ap-shanghai.myqcloud.com//940504/posts/Circular_Buffer_Animation.gif&#34;&gt;&lt;/p&gt;
&lt;p&gt;目前我们只需要考虑：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;存储啥数据类型&lt;/li&gt;
&lt;li&gt;数据如何存放&lt;/li&gt;
&lt;li&gt;何时空间满了需要扩容&lt;/li&gt;
&lt;li&gt;不能丢失未消费数据&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;k8s中的源码：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 源码路径k8s.io/utils/buffer/ring_growing.go&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;buffer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 非线程安全、可增长的环形缓冲区&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RingGrowing&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 存任意数据的数组&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 缓冲区大小&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 第一个可用的元素位置索引&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 未消费的元素数量&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 初始化一个RingBuffer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewRingGrowing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;initialSize&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RingGrowing&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RingGrowing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([]&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{},&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;initialSize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;initialSize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 取出未消费元素中的第一个元素&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RingGrowing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ReadOne&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{},&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readable&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Remove reference to the object to help GC&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 这种情况就是读到数组最后一个元素了，下次读就得从列表的头部开始，以免越界&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 在buffer尾部添加一个元素，buffer满了就扩容&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RingGrowing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WriteOne&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{})&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 满了的情况&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 新开辟一个两倍大小的数组&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newData&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([]&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{},&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 未消费的元素在数组两端的情况&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;copied&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:])&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;copied&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)])&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newData&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;newN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readable&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;readable&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;br /&gt;client-go中的这个buffer是非线程安全、可增长、无边界的先进先出环形缓冲区，因此，在此client-go ringBuffer基础上可以继续考虑下面几个问题：&lt;/p&gt;</description>
    </item>
    <item>
      <title>读redis-py客户端源码</title>
      <link>https://940504.top/posts/redis-py%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%BA%90%E7%A0%81%E5%88%9D%E8%AF%BB/</link>
      <pubDate>Fri, 06 Mar 2020 14:43:33 +0800</pubDate>
      <guid>https://940504.top/posts/redis-py%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%BA%90%E7%A0%81%E5%88%9D%E8%AF%BB/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;看别人的代码也是对自己思维和经验的学习丰富过程&lt;/p&gt;
&lt;p&gt;作为一个初学者，之前写过的代码量较少，很少涉及到完整的项目开发，看完redis-py库后，get到其中的&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;连接保活机制&lt;/li&gt;
&lt;li&gt;连接池的实现&lt;/li&gt;
&lt;li&gt;开辟buffer存入从socket接收来的数据及buffer管理&lt;/li&gt;
&lt;li&gt;熟悉了RESP协议&lt;/li&gt;
&lt;li&gt;多进程多线程的情况下，利用锁确保连接池数据结构安全&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我读的过程中觉得值得注意的是，&lt;code&gt;_in_use_connections&lt;/code&gt;使用集合结构；此连接池不是在初始化时创建好一定数量的tcp连接；其中用了两个互斥锁，一个保护连接池，一个保护多进程的池；较多的连接重连，确保连接可用&lt;/p&gt;
&lt;h2 id=&#34;执行过程&#34;&gt;执行过程&lt;/h2&gt;
&lt;p&gt;该库主要有Redis、Connection、ConnectionPool、PythonParse、SocketBuffer几个类，下面大概理了一下redis-py的执行过程&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;开始使用redis-py客户端&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;class Redis实例化&lt;/p&gt;
&lt;p&gt;可以关注下面几个参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;socket_timeout=None,&lt;/li&gt;
&lt;li&gt;socket_connect_timeout=None,&lt;/li&gt;
&lt;li&gt;socket_keepalive=None,&lt;/li&gt;
&lt;li&gt;socket_keepalive_options=None,&lt;/li&gt;
&lt;li&gt;connection_pool=None,&lt;/li&gt;
&lt;li&gt;retry_on_timeout=False,&lt;/li&gt;
&lt;li&gt;max_connections=None,&lt;/li&gt;
&lt;li&gt;single_connection_client=False, # 是否单个连接，不用连接池&lt;/li&gt;
&lt;li&gt;health_check_interval=0,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;class ConnectionPool连接池初始化&lt;code&gt;ConnectionPool()&lt;/code&gt;，此时尚未创建连接&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; # 此处定义连接池最大连接数
 max_connections = max_connections or 2 ** 31

 # fork_safe，在_checkpid()方法中用到，保护临界区的锁。这个锁是在进程id改变时获得的。比如fork出一个子进程后，子进程id和池对象中保存的id不一致，那么子进程中的多个线程都可能会先获取此锁，第一个获得锁的线程将重置此池的数据结构并最终释放锁对象，后续的线程再执行时，pid已于子线程池中的pid熟悉一致，不再做其他操作，在下面也会有提到
 self._fork_lock = threading.Lock()

 # 定义了并初始化已创建连接数、使用中的链接、可用的连接等数据结构
 self._lock = threading.Lock()
 self._created_connections = 0
 self._available_connections = []
 self._in_use_connections = set()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意此处&lt;code&gt;_in_use_connections&lt;/code&gt;使用了集合存储池中的连接对象，这个与python数据类型时间复杂度有关，可&lt;a href=&#34;https://wiki.python.org/moin/TimeComplexity&#34;&gt;点此参考官网&lt;/a&gt;，集合的内部实现与字典极为相似，此集合对象只用到两个操作，&lt;code&gt;add&lt;/code&gt;和&lt;code&gt;remove&lt;/code&gt;，时间复杂度均为O(1)，（有误烦请指正🤡🤡🤡）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;初始化Redis-Client状态信息完毕，此时还没有任何连接被创建&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;假设开始执行 &lt;code&gt;r.set(&#39;foo&#39;, &#39;baiqi&#39;)&lt;/code&gt;，此方法返回&lt;code&gt;r.excute_command()&lt;/code&gt;的结果&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;首先尝试从池中获取一个Connection对象 &lt;code&gt;pool.get_connection(command_name, **options)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;获取时得先执行下&lt;code&gt;_checkpid()&lt;/code&gt;方法，再执行&lt;code&gt;get_connection()&lt;/code&gt;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
