<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Blume&apos;s Skylog</title><description>全栈开发 · AI 应用</description><link>https://blog.81vm3.xyz/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>6.16.8</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年10月7日 05:08:08</lastBuildDate><item><title>Grafana 可视化与监控</title><link>https://blog.81vm3.xyz/posts/grafana/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/grafana/</guid><description>Grafana 的定位、常见数据源与 Grafana + Prometheus 经典监控链路。</description><pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Grafana 是一个开源的数据可视化和监控平台，主要用于把各种数据源中的指标（Metrics）、日志（Logs）和追踪（Traces）展示成直观的仪表盘（Dashboard），方便运维、开发和业务人员监控系统状态。&lt;/p&gt;
&lt;section&gt;&lt;h3&gt;Grafana 能做什么？&lt;a href=&quot;#grafana-能做什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;section&gt;&lt;h4&gt;1. 数据可视化&lt;a href=&quot;#1-数据可视化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&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;li&gt;仪表盘&lt;/li&gt;
&lt;li&gt;热力图&lt;/li&gt;
&lt;li&gt;表格&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;CPU使用率&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│      ╱╲&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│    ╱╱  ╲&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│  ╱╱     ╲&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└───────────── 时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;2. 系统监控&lt;a href=&quot;#2-系统监控&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;常用于监控：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;服务器 CPU、内存、磁盘&lt;/li&gt;
&lt;li&gt;Kubernetes 集群&lt;/li&gt;
&lt;li&gt;数据库性能&lt;/li&gt;
&lt;li&gt;应用程序运行状态&lt;/li&gt;
&lt;li&gt;网络流量&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;3. 告警通知&lt;a href=&quot;#3-告警通知&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&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;li&gt;Slack&lt;/li&gt;
&lt;li&gt;Webhook&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;CPU 使用率连续 5 分钟超过 90%，自动报警。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;Grafana 的数据来源&lt;a href=&quot;#grafana-的数据来源&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Grafana 本身不存储监控数据，它负责展示数据。&lt;/p&gt;&lt;p&gt;常见搭配：&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;数据源&lt;/th&gt;&lt;th&gt;用途&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Prometheus&lt;/td&gt;&lt;td&gt;监控指标（最常见）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;InfluxDB&lt;/td&gt;&lt;td&gt;时序数据库&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Elasticsearch&lt;/td&gt;&lt;td&gt;日志分析&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MySQL&lt;/td&gt;&lt;td&gt;业务数据&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PostgreSQL&lt;/td&gt;&lt;td&gt;业务数据&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Loki&lt;/td&gt;&lt;td&gt;日志监控&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tempo&lt;/td&gt;&lt;td&gt;链路追踪&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;Grafana + Prometheus 是最经典组合&lt;a href=&quot;#grafana--prometheus-是最经典组合&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;架构通常如下：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;服务器&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Node Exporter&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Prometheus&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Grafana&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Dashboard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;工作流程：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Node Exporter 收集服务器指标&lt;/li&gt;
&lt;li&gt;Prometheus 定时拉取指标&lt;/li&gt;
&lt;li&gt;Grafana 从 Prometheus 查询数据&lt;/li&gt;
&lt;li&gt;Grafana 展示监控图表&lt;/li&gt;
&lt;/ol&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;一个典型场景&lt;a href=&quot;#一个典型场景&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;比如你有一个 Java 网站：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;用户访问网站&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Spring Boot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Prometheus&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Grafana&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Grafana 可以实时展示：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;QPS（每秒请求数）&lt;/li&gt;
&lt;li&gt;接口响应时间&lt;/li&gt;
&lt;li&gt;错误率&lt;/li&gt;
&lt;li&gt;JVM 内存&lt;/li&gt;
&lt;li&gt;GC 次数&lt;/li&gt;
&lt;li&gt;数据库连接数&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;为什么 Grafana 这么流行？&lt;a href=&quot;#为什么-grafana-这么流行&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&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;li&gt;Dashboard 丰富&lt;/li&gt;
&lt;li&gt;Kubernetes/云原生生态事实标准&lt;/li&gt;
&lt;li&gt;插件生态完善&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;很多公司会使用：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Grafana + Prometheus（监控）&lt;/li&gt;
&lt;li&gt;Grafana + Loki（日志）&lt;/li&gt;
&lt;li&gt;Grafana + Tempo（链路追踪）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;形成完整的可观测性（Observability）平台。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;一句话理解&lt;a href=&quot;#一句话理解&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Prometheus 负责“采集和存储监控数据”，Grafana 负责“把数据画成好看的图表并进行告警”。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果你是在学习 DevOps、运维、云原生或 Kubernetes，那么 Grafana 几乎是必学工具。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>微服务之间如何传递 trace</title><link>https://blog.81vm3.xyz/posts/trace-propagation/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/trace-propagation/</guid><description>跨服务传递的是 trace 上下文而非 tracer：HTTP header、gRPC metadata 与 MQ 消息头的标准做法。</description><pubDate>Wed, 22 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;跨微服务时，靠的是“上下文传播”，不是接口 body 显式保留 trace id。&lt;/p&gt;
&lt;p&gt;先区分 3 个东西：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;tracer&lt;/strong&gt;：代码里 &lt;code&gt;otel.Tracer(...)&lt;/code&gt; 的对象，表示哪段代码在打点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;trace id&lt;/strong&gt;：一整条链路的 ID&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;span id&lt;/strong&gt;：链路里某个节点的 ID&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;微服务之间传递的是 trace id/span 上下文，不是 tracer。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;HTTP 场景&lt;a href=&quot;#http-场景&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;标准做法是放在请求头里，通常是 W3C Trace Context：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;traceparent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tracestate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;可选 &lt;code&gt;baggage&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;流程是：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;服务 A 收到请求，创建或继续一个 trace&lt;/li&gt;
&lt;li&gt;服务 A 调服务 B 前，把当前 trace context 注入到 HTTP header&lt;/li&gt;
&lt;li&gt;服务 B 收到请求后，从 header 提取 trace context&lt;/li&gt;
&lt;li&gt;服务 B 基于这个 context 创建自己的 span&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这样 A 和 B 的 span 就会落到同一个 trace 里。&lt;/p&gt;&lt;p&gt;所以一般不需要你在接口 JSON 里专门加：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;traceId&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;...&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;除非你有业务上的特殊需求。对 tracing 本身来说，不该这么做，原因是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;污染业务接口契约&lt;/li&gt;
&lt;li&gt;容易和真实 OTel 上下文不一致&lt;/li&gt;
&lt;li&gt;标准库/中间件已经能自动处理 header&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;HTTP 里通常像这样：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;服务端：&lt;strong&gt;Extract&lt;/strong&gt;（从入站 header 恢复上下文）&lt;/li&gt;
&lt;li&gt;客户端：&lt;strong&gt;Inject&lt;/strong&gt;（把上下文写入出站 header）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Go + OpenTelemetry 的服务端提取示例：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 服务端：从入站请求 header 中提取上下文，再基于它创建 span&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;otel&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetTextMapPropagator&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;Extract&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;propagation&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;HeaderCarrier&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Header&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tracer&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Start&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;handle-request&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;defer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;End&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;客户端注入示例：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 客户端：把当前上下文注入到出站请求 header&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;httptest&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;NewRequest&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;http://service-b/api&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;otel&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetTextMapPropagator&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;Inject&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;propagation&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;HeaderCarrier&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Header&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;gRPC 与消息队列&lt;a href=&quot;#grpc-与消息队列&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;gRPC 也是一样，只是不是 HTTP header，而是 gRPC metadata。原理完全相同：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;client interceptor 注入&lt;/li&gt;
&lt;li&gt;server interceptor 提取&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;消息队列也类似，通常放在消息 header / metadata 里，不放消息 body。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;实务建议&lt;a href=&quot;#实务建议&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;HTTP：用 &lt;code&gt;traceparent&lt;/code&gt; 这些标准 header&lt;/li&gt;
&lt;li&gt;gRPC：用 metadata&lt;/li&gt;
&lt;li&gt;MQ/Kafka：用 message headers&lt;/li&gt;
&lt;li&gt;不要把 trace id 做成业务接口字段，除非只是为了调试展示&lt;/li&gt;
&lt;li&gt;可以额外返回一个 &lt;code&gt;X-Trace-ID&lt;/code&gt; 给前端或调用方排查问题，但这只是便于观察，不是主链路传播的标准方式&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;相关概念见 OpenTelemetry 与链路追踪笔记。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>kubectl port-forward 端口转发</title><link>https://blog.81vm3.xyz/posts/k8s-port-forward/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/k8s-port-forward/</guid><description>kubectl port-forward 转发 Pod/Service、让局域网访问以及常用排查命令。</description><pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;k8s 端口转发&lt;a href=&quot;#k8s-端口转发&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;最常用的是 &lt;code&gt;kubectl port-forward&lt;/code&gt;。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;转发 Pod&lt;a href=&quot;#转发-pod&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;把某个 Pod 的 &lt;code&gt;8080&lt;/code&gt; 转到本机 &lt;code&gt;18080&lt;/code&gt;：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod/&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;18080:8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;如果 Pod 在指定 namespace：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;namespace&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod/&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;18080:8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;访问方式：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;http://127.0.0.1:18080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;转发 Service&lt;a href=&quot;#转发-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通常转发 Service 更稳：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;namespace&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc/&amp;lt;service-name&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;18080:8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;注意这里后面的 &lt;code&gt;8080&lt;/code&gt; 是 Service 的端口，不一定是容器端口。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;让局域网其他机器也能访问&lt;a href=&quot;#让局域网其他机器也能访问&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;默认只监听本机 &lt;code&gt;127.0.0.1&lt;/code&gt;。如果要让其他机器访问你这台主机上的转发端口：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;namespace&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--address&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.0.0.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod/&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;18080:8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;然后其他机器访问：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;http://你的主机IP:18080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;常用排查命令&lt;a href=&quot;#常用排查命令&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pods&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;namespace&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;namespace&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;describe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;namespace&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;注意事项&lt;a href=&quot;#注意事项&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubectl port-forward&lt;/code&gt; 是前台命令，终端关闭后转发会断开。&lt;/li&gt;
&lt;li&gt;目标端口必须是 Pod 或 Service 实际监听的端口。&lt;/li&gt;
&lt;li&gt;如果是长期暴露服务，不建议靠 port-forward，应该考虑 &lt;code&gt;NodePort&lt;/code&gt;、&lt;code&gt;LoadBalancer&lt;/code&gt;、Ingress 或反向代理。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Kubernetes&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>kubectl 常用命令速查</title><link>https://blog.81vm3.xyz/posts/kubectl-commands/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/kubectl-commands/</guid><description>kubectl 查看集群/资源/日志、进入容器、本地访问服务与部署删除的常用命令。</description><pubDate>Fri, 20 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;kubectl 常用命令&lt;a href=&quot;#kubectl-常用命令&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;查看当前集群&lt;a href=&quot;#查看当前集群&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;current-context&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nodes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;查看资源&lt;a href=&quot;#查看资源&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;all&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pods&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;configmap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;secret&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;job&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;查看详情&lt;a href=&quot;#查看详情&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;describe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;describe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;user-api-deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;describe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;user-api&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;看日志&lt;a href=&quot;#看日志&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy/user-api-deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;job/ai-migrate-job&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;进入容器&lt;a href=&quot;#进入容器&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-it&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;本地访问服务&lt;a href=&quot;#本地访问服务&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc/user-api&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;18000:80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;http://localhost:18000/readyz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;部署和删除&lt;a href=&quot;#部署和删除&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kustomize&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy/overlay/dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-k&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy/overlay/dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-k&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy/overlay/dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;重启和发布状态&lt;a href=&quot;#重启和发布状态&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rollout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deployment/user-api-deployment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rollout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deployment/user-api-deployment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rollout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;history&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deployment/user-api-deployment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;看事件&lt;a href=&quot;#看事件&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;events&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--sort-by=.lastTimestamp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;相关笔记：Kubernetes 排障手册、K8s 本地实战&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>k8s Service：给一组 Pod 稳定入口</title><link>https://blog.81vm3.xyz/posts/k8s-service/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/k8s-service/</guid><description>Service 解决的问题、关键字段、四种类型与排障要点。</description><pubDate>Tue, 03 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;k8s Service&lt;a href=&quot;#k8s-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Service 给一组 Pod 提供稳定访问入口。Pod 会销毁、重建、换 IP，但 Service 的名字和虚拟 IP 相对稳定。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;Pasted image 20260616204746.png&quot; loading=&quot;lazy&quot; width=&quot;441&quot; height=&quot;247&quot; src=&quot;/_astro/pasted-image-20260616204746.3ppGTFOi_Z1cQe5d.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20260616204746.png&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;section&gt;&lt;h2&gt;它解决什么问题&lt;a href=&quot;#它解决什么问题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Deployment 后面可能有多个 Pod：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user-api Pod A: 10.1.0.11&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user-api Pod B: 10.1.0.12&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user-api Pod C: 10.1.0.13&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;客户端不应该记住这些 Pod IP，因为 Pod 随时会变化。Service 通过 label selector 找到这些 Pod，对外提供一个稳定入口。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;client -&amp;gt; Service -&amp;gt; matching Pods&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;最小示例&lt;a href=&quot;#最小示例&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;user-service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ClusterIP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;user-service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;targetPort&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;8000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;关键字段：&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;字段&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;selector&lt;/code&gt;&lt;/td&gt;&lt;td&gt;找到带有对应 label 的 Pod&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;port&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Service 暴露的端口&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;targetPort&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Pod 容器里的端口&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Service 暴露方式&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Service 类型&lt;a href=&quot;#service-类型&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;类型&lt;/th&gt;&lt;th&gt;用途&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ClusterIP&lt;/code&gt;&lt;/td&gt;&lt;td&gt;只在集群内部访问，默认类型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NodePort&lt;/code&gt;&lt;/td&gt;&lt;td&gt;通过每台 Node 的端口访问&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LoadBalancer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;云厂商创建负载均衡器&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ExternalName&lt;/code&gt;&lt;/td&gt;&lt;td&gt;映射到外部 DNS 名称&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;实际项目例子&lt;a href=&quot;#实际项目例子&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;项目里有：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;user-api&lt;/code&gt;：把流量转发到 &lt;code&gt;app: user-api&lt;/code&gt; 的 Pod。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;admin-api&lt;/code&gt;：把流量转发到 &lt;code&gt;app: admin-api&lt;/code&gt; 的 Pod。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;本地调试时常用 &lt;code&gt;port-forward&lt;/code&gt;：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc/user-api&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;18000:80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;http://localhost:18000/readyz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;常用命令&lt;a href=&quot;#常用命令&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;describe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;user-api&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;endpoints&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;如果 Service 没有转发到 Pod，优先检查：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Service 的 &lt;code&gt;selector&lt;/code&gt; 是否匹配 Pod 的 &lt;code&gt;labels&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Pod 是否处于 Ready 状态。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;targetPort&lt;/code&gt; 是否等于容器实际监听端口。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;相关笔记：pod、k8s deployment、Kubernetes 排障手册&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Kubernetes 集群架构总览</title><link>https://blog.81vm3.xyz/posts/k8s-architecture/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/k8s-architecture/</guid><description>K8s 集群的控制平面组件（apiserver/etcd/scheduler/controller-manager）与节点组件（kubelet/kube-proxy）。</description><pubDate>Thu, 12 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Kubernetes 背后的架构概念。&lt;/p&gt;
&lt;p&gt;Kubernetes 集群由一个控制平面和一组用于运行容器化应用的工作机器组成， 这些工作机器称作节点（Node）。每个集群至少需要一个工作节点来运行 Pod。&lt;/p&gt;
&lt;p&gt;工作节点托管着组成应用负载的 Pod。控制平面管理集群中的工作节点和 Pod。 在生产环境中，控制平面通常跨多台计算机运行，而一个集群通常运行多个节点，以提供容错和高可用。&lt;/p&gt;
&lt;p&gt;本文概述了构建一个完整且可运行的 Kubernetes 集群所需的各种组件。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://kubernetes.io/images/docs/kubernetes-cluster-architecture.svg&quot; alt=&quot;控制平面（kube-apiserver、etcd、kube-controller-manager、kube-scheduler）和多个节点。每个节点运行 kubelet 和 kube-proxy。&quot; /&gt;&lt;figcaption&gt;控制平面（kube-apiserver、etcd、kube-controller-manager、kube-scheduler）和多个节点。每个节点运行 kubelet 和 kube-proxy。&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;图 1. Kubernetes 集群组件。&lt;/p&gt;
&lt;p&gt;关于此架构&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#kube-proxy&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;控制平面组件 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#control-plane-components&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#控制平面组件&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;控制平面组件会为集群做出全局决策，比如资源的调度。 以及检测和响应集群事件，例如当不满足 Deployment 的 &lt;code&gt;[replicas](https://kubernetes.io/zh-cn/docs/reference/glossary/?all=true#term-replica)&lt;/code&gt; 字段时，要启动新的 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/&quot; target=&quot;_blank&quot;&gt;Pod&lt;/a&gt;）。&lt;/p&gt;&lt;p&gt;控制平面组件可以在集群中的任何节点上运行。 然而，为了简单起见，安装脚本通常会在同一个计算机上启动所有控制平面组件， 并且不会在此计算机上运行用户容器。 请参阅&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/high-availability/&quot; target=&quot;_blank&quot;&gt;使用 kubeadm 构建高可用性集群&lt;/a&gt;中关于跨多机器安装控制平面的示例。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;kube-apiserver&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#kube-apiserver&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#kube-apiserver&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;API 服务器是 Kubernetes &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/reference/glossary/?all=true#term-control-plane&quot; target=&quot;_blank&quot;&gt;控制平面&lt;/a&gt;的组件， 该组件负责公开了 Kubernetes API，负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。&lt;/p&gt;&lt;p&gt;Kubernetes API 服务器的主要实现是 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/kube-apiserver/&quot; target=&quot;_blank&quot;&gt;kube-apiserver&lt;/a&gt;。 &lt;code&gt;kube-apiserver&lt;/code&gt; 设计上考虑了水平扩缩，也就是说，它可通过部署多个实例来进行扩缩。 你可以运行 &lt;code&gt;kube-apiserver&lt;/code&gt; 的多个实例，并在这些实例之间平衡流量。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;etcd&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#etcd&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#etcd&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一致且高可用的键值存储，用作 Kubernetes 所有集群数据的后台数据库。&lt;/p&gt;&lt;p&gt;如果你的 Kubernetes 集群使用 etcd 作为其后台数据库， 请确保你针对这些数据有一份 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/configure-upgrade-etcd/#backing-up-an-etcd-cluster&quot; target=&quot;_blank&quot;&gt;备份&lt;/a&gt;计划。&lt;/p&gt;&lt;p&gt;你可以在官方&lt;a href=&quot;https://etcd.io/docs/&quot; target=&quot;_blank&quot;&gt;文档&lt;/a&gt;中找到有关 etcd 的深入知识。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;kube-scheduler&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#kube-scheduler&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#kube-scheduler&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;kube-scheduler&lt;/code&gt; 是&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/reference/glossary/?all=true#term-control-plane&quot; target=&quot;_blank&quot;&gt;控制平面&lt;/a&gt;的组件， 负责监视新创建的、未指定运行&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/nodes/&quot; target=&quot;_blank&quot;&gt;节点&lt;/a&gt;的 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/&quot; target=&quot;_blank&quot;&gt;Pod&lt;/a&gt;，并选择节点来让 Pod 在上面运行。&lt;/p&gt;&lt;p&gt;调度决策考虑的因素包括单个 Pod 及多个 Pod 集合的&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/reference/glossary/?all=true#term-infrastructure-resource&quot; target=&quot;_blank&quot;&gt;资源&lt;/a&gt;需求、 软硬件及策略约束、亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;kube-controller-manager&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#kube-controller-manager&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#kube-controller-manager&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;kube-controller-manager 是运行&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/controller/&quot; target=&quot;_blank&quot;&gt;控制器&lt;/a&gt;进程的控制平面组件。&lt;/p&gt;&lt;p&gt;从逻辑上讲，每个&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/controller/&quot; target=&quot;_blank&quot;&gt;控制器&lt;/a&gt;都是一个单独的进程， 但是为了降低复杂性，它们都被编译到同一个可执行文件，并在同一个进程中运行。&lt;/p&gt;&lt;p&gt;控制器有许多不同类型。以下是一些例子：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Node 控制器：负责在节点出现故障时进行通知和响应&lt;/li&gt;
&lt;li&gt;Job 控制器：监测代表一次性任务的 Job 对象，然后创建 Pod 来运行这些任务直至完成&lt;/li&gt;
&lt;li&gt;EndpointSlice 控制器：填充 EndpointSlice 对象（以提供 Service 和 Pod 之间的链接）。&lt;/li&gt;
&lt;li&gt;ServiceAccount 控制器：为新的命名空间创建默认的 ServiceAccount。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;以上并不是一个详尽的列表。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;cloud-controller-manager&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#cloud-controller-manager&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#cloud-controller-manager&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一个 Kubernetes &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/reference/glossary/?all=true#term-control-plane&quot; target=&quot;_blank&quot;&gt;控制平面&lt;/a&gt;组件， 嵌入了特定于云平台的控制逻辑。 云控制器管理器（Cloud Controller Manager）允许将你的集群连接到云提供商的 API 之上， 并将与该云平台交互的组件同与你的集群交互的组件分离开来。&lt;/p&gt;&lt;p&gt;&lt;code&gt;cloud-controller-manager&lt;/code&gt; 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes，或者在本地计算机中运行学习环境， 所部署的集群不包含云控制器管理器。&lt;/p&gt;&lt;p&gt;与 &lt;code&gt;kube-controller-manager&lt;/code&gt; 类似，&lt;code&gt;cloud-controller-manager&lt;/code&gt; 将若干逻辑上独立的控制回路组合到同一个可执行文件中，以同一进程的方式供你运行。 你可以对其执行水平扩容（运行不止一个副本）以提升性能或者增强容错能力。&lt;/p&gt;&lt;p&gt;下面的控制器都包含对云平台驱动的依赖：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Node 控制器：用于在节点终止响应后检查云平台以确定节点是否已被删除&lt;/li&gt;
&lt;li&gt;Route 控制器：用于在底层云基础架构中设置路由&lt;/li&gt;
&lt;li&gt;Service 控制器：用于创建、更新和删除云平台上的负载均衡器&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;节点组件 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#node-components&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#节点组件&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;节点组件会在每个节点上运行，负责维护运行的 Pod 并提供 Kubernetes 运行时环境。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;kubelet&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#kubelet&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#kubelet&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;kubelet&lt;/code&gt; 会在集群中每个&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/nodes/&quot; target=&quot;_blank&quot;&gt;节点（node）&lt;/a&gt;上运行。 它保证&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/containers/&quot; target=&quot;_blank&quot;&gt;容器（containers）&lt;/a&gt;都运行在 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/&quot; target=&quot;_blank&quot;&gt;Pod&lt;/a&gt; 中。&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/kubelet/&quot; target=&quot;_blank&quot;&gt;kubelet&lt;/a&gt; 接收一组通过各类机制提供给它的 PodSpec，确保这些 PodSpec 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;kube-proxy（可选） &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#kube-proxy&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#kube-proxy可选&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;根据 Service 和它对应的后端 Pod 列表，在每个节点上配置转发规则，让发往 Service 的流量能被送到某个后端
Pod。&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/reference/command-line-tools-reference/kube-proxy/&quot; target=&quot;_blank&quot;&gt;kube-proxy&lt;/a&gt; 是集群中每个&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/nodes/&quot; target=&quot;_blank&quot;&gt;节点（node）&lt;/a&gt;上所运行的网络代理， 实现 Kubernetes &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/&quot; target=&quot;_blank&quot;&gt;服务（Service）&lt;/a&gt; 概念的一部分。&lt;/p&gt;&lt;p&gt;kube-proxy 维护节点上的一些网络规则， 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。&lt;/p&gt;&lt;p&gt;如果操作系统提供了可用的数据包过滤层，则 kube-proxy 会通过它来实现网络规则。 否则，kube-proxy 仅做流量转发。&lt;/p&gt;&lt;p&gt;如果你使用&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#network-plugins&quot; target=&quot;_blank&quot;&gt;网络插件&lt;/a&gt;为 Service 实现本身的数据包转发， 并提供与 kube-proxy 等效的行为，那么你不需要在集群中的节点上运行 kube-proxy。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;容器运行时 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#container-runtime&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#容器运行时&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。&lt;/p&gt;&lt;p&gt;Kubernetes 支持许多容器运行环境，例如 &lt;a href=&quot;https://containerd.io/docs/&quot; target=&quot;_blank&quot;&gt;containerd&lt;/a&gt;、 &lt;a href=&quot;https://cri-o.io/#what-is-cri-o&quot; target=&quot;_blank&quot;&gt;CRI-O&lt;/a&gt; 以及 &lt;a href=&quot;https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.md&quot; target=&quot;_blank&quot;&gt;Kubernetes CRI (容器运行环境接口)&lt;/a&gt; 的其他任何实现。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;插件（Addons） &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#addons&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#插件addons&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;插件使用 Kubernetes 资源（&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/&quot; target=&quot;_blank&quot;&gt;DaemonSet&lt;/a&gt;、 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/&quot; target=&quot;_blank&quot;&gt;Deployment&lt;/a&gt; 等）实现集群功能。 因为这些插件提供集群级别的功能，插件中命名空间域的资源属于 &lt;code&gt;kube-system&lt;/code&gt; 命名空间。&lt;/p&gt;&lt;p&gt;下面描述众多插件中的几种。有关可用插件的完整列表， 请参见&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/addons/&quot; target=&quot;_blank&quot;&gt;插件（Addons）&lt;/a&gt;。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;DNS&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#dns&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#dns&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;尽管其他插件都并非严格意义上的必需组件，但几乎所有 Kubernetes 集群都应该有&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/services-networking/dns-pod-service/&quot; target=&quot;_blank&quot;&gt;集群 DNS&lt;/a&gt;， 因为很多示例都需要 DNS 服务。&lt;/p&gt;&lt;p&gt;集群 DNS 是一个 DNS 服务器，和环境中的其他 DNS 服务器一起工作，它为 Kubernetes 服务提供 DNS 记录。&lt;/p&gt;&lt;p&gt;Kubernetes 启动的容器自动将此 DNS 服务器包含在其 DNS 搜索列表中。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Web 界面（仪表盘） &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#web-ui-dashboard&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#web-界面仪表盘&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/tasks/access-application-cluster/web-ui-dashboard/&quot; target=&quot;_blank&quot;&gt;Dashboard&lt;/a&gt; 是 Kubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身，并进行故障排除。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;容器资源监控 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#container-resource-monitoring&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#容器资源监控&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/tasks/debug/debug-cluster/resource-usage-monitoring/&quot; target=&quot;_blank&quot;&gt;容器资源监控&lt;/a&gt; 将关于容器的一些常见的时序度量值保存到一个集中的数据库中，并提供浏览这些数据的界面。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;集群层面日志 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#cluster-level-logging&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#集群层面日志&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/logging/&quot; target=&quot;_blank&quot;&gt;集群层面日志&lt;/a&gt;机制负责将容器的日志数据保存到一个集中的日志存储中， 这种集中日志存储提供搜索和浏览接口。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;网络插件 &lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/architecture/#network-plugins&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;&lt;a href=&quot;#网络插件&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins&quot; target=&quot;_blank&quot;&gt;网络插件&lt;/a&gt; 是实现容器网络接口（CNI）规范的软件组件。它们负责为 Pod 分配 IP 地址， 并使这些 Pod 能在集群内部相互通信&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>一致性哈希：consistent 与 rendezvous 的对比</title><link>https://blog.81vm3.xyz/posts/consistent-hashing/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/consistent-hashing/</guid><description>两种分布式哈希的均匀度与耗时对比结论：节点少选 rendezvous，节点多且时间敏感选 consistent。</description><pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;一致性哈希要解决的问题：在节点集合会变化的分布式系统里，把 key 稳定地映射到节点上，使得增删节点时只影响尽量少的 key。常见实现有两类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistent Hashing（环 + 虚拟节点）&lt;/strong&gt;：把节点和 key 都哈希到一个环上，key 沿环顺时针找到第一个节点；用虚拟节点改善均匀度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendezvous Hashing（HRW，Highest Random Weight）&lt;/strong&gt;：对每个 key，计算它与所有节点的哈希分数，取分数最高的节点。没有环、没有虚拟节点，纯计算。&lt;/li&gt;
&lt;/ul&gt;
&lt;section&gt;&lt;h2&gt;对比结论&lt;a href=&quot;#对比结论&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;参考资料：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.huawei.com/consumer/cn/forum/topic/0203810951415790238&quot; target=&quot;_blank&quot;&gt;16 张图解带你掌握一致性哈希算法 - 华为开发者话题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/1924514679499237285&quot; target=&quot;_blank&quot;&gt;Consistent 和 Rendezvous 两种分布式 Hash 的比较 - 知乎&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pdai.tech/md/algorithm/alg-domain-distribute-x-consistency-hash.html&quot; target=&quot;_blank&quot;&gt;分布式算法 - 一致性 Hash 算法 - Java 全栈知识体系&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;实测的两条核心结论：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;rendezvous 的均匀度更好&lt;/strong&gt;，所有场景的均值偏差都在 10% 以内。但当集群节点数较多时，rendezvous 更耗时：100 个节点时，rendezvous 的耗时是 consistent 的一倍（因为每个 key 都要和全部节点算一遍分数，O(n)）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;consistent 随虚拟节点数量增加，均匀性越来越好&lt;/strong&gt;，且虚拟节点数量基本不影响调度用时（哈希环 + 二分查找，O(log n)）。但均匀度和 rendezvous 比始终有差距。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;怎么选&lt;a href=&quot;#怎么选&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;节点数较少：直接选 rendezvous hash，简单且均匀。&lt;/li&gt;
&lt;li&gt;节点数较多且时间敏感：选 consistent hash。&lt;/li&gt;
&lt;li&gt;节点数较多但对均匀性要求更高、能接受耗时：依然选 rendezvous hash 来确保均匀性。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;一句话：rendezvous 用计算时间换均匀度；consistent 用虚拟节点改善均匀度，查询则是哈希环上 O(log n) 的二分。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>微服务鉴权与网关职责</title><link>https://blog.81vm3.xyz/posts/gateway-auth/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/gateway-auth/</guid><description>Gateway 负责认证、Service 负责授权：身份上下文透传、反例风险与文件服务落地场景。</description><pubDate>Tue, 27 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;微服务鉴权与网关职责&lt;a href=&quot;#微服务鉴权与网关职责&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;核心结论&lt;a href=&quot;#核心结论&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Gateway 负责 Authentication（你是谁）&lt;/li&gt;
&lt;li&gt;Microservice 负责 Authorization（你能干什么）&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Gateway 应该做什么&lt;a href=&quot;#gateway-应该做什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;验证登录态：JWT / OAuth2 / Session / API Key&lt;/li&gt;
&lt;li&gt;提取并传递身份上下文：&lt;code&gt;x-user-id&lt;/code&gt;、&lt;code&gt;x-user-role&lt;/code&gt;、&lt;code&gt;x-tenant-id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;公共安全能力：限流、黑名单、IP 风控、CORS、TLS、WAF、审计日志、Tracing&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Service 必须做什么&lt;a href=&quot;#service-必须做什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;校验资源归属（是否本人数据）&lt;/li&gt;
&lt;li&gt;校验角色权限（RBAC）&lt;/li&gt;
&lt;li&gt;校验属性条件（ABAC，可选）&lt;/li&gt;
&lt;li&gt;校验租户边界（tenant）&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;反例&lt;a href=&quot;#反例&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;只在 Gateway 校验 JWT，service 完全信任 header。&lt;/p&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;SSRF 间接越权&lt;/li&gt;
&lt;li&gt;资源 ID 枚举导致越权操作&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;gRPC 透传身份（Go）&lt;a href=&quot;#grpc-透传身份go&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;md&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Pairs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;x-user-id&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;123&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;x-user-role&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;user&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;NewOutgoingContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;md&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// server side&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;md&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;FromIncomingContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;uid&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;md&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;x-user-id&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;role&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;md&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;x-user-role&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;说明：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;metadata 适合内部身份上下文透传&lt;/li&gt;
&lt;li&gt;不能只“读到 uid 就执行业务”，必须继续做业务授权校验&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;更成熟的内部安全&lt;a href=&quot;#更成熟的内部安全&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;内部签名头（例如：&lt;code&gt;x-auth-signature&lt;/code&gt; + &lt;code&gt;x-request-ts&lt;/code&gt;）防伪造&lt;/li&gt;
&lt;li&gt;Service Mesh（Istio/Linkerd）做服务间 mTLS 身份认证&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;文件服务场景落地&lt;a href=&quot;#文件服务场景落地&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;外部：&lt;code&gt;HTTP/JSON -&amp;gt; Gateway&lt;/code&gt;&lt;br /&gt;
内部：&lt;code&gt;Gateway -&amp;gt; gRPC filesystem-service&lt;/code&gt;&lt;/p&gt;&lt;p&gt;filesystem-service 关注：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;元数据、分片、hash、配额、权限&lt;/li&gt;
&lt;li&gt;对象存储交互&lt;/li&gt;
&lt;li&gt;presigned URL 签发&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;大文件推荐：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Gateway 只签发 URL&lt;/li&gt;
&lt;li&gt;客户端直传对象存储（S3/OSS/MinIO）&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;快速检查清单&lt;a href=&quot;#快速检查清单&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;是否明确区分认证与授权&lt;/li&gt;
&lt;li&gt;service 是否做了资源归属校验&lt;/li&gt;
&lt;li&gt;是否有 role/tenant 维度校验&lt;/li&gt;
&lt;li&gt;是否限制了内部伪造请求风险&lt;/li&gt;
&lt;li&gt;上传链路是否避免 Gateway 传大文件&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Minikube 本地集群</title><link>https://blog.81vm3.xyz/posts/minikube/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/minikube/</guid><description>Minikube 的启停、复用其内部 Docker 构建镜像以及常用调试命令。</description><pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Minikube&lt;a href=&quot;#minikube&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Minikube 是本地单节点 Kubernetes 集群，适合学习和本地验证部署 YAML。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;启动和停止&lt;a href=&quot;#启动和停止&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stop&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;确认 kubectl 连到 minikube&lt;a href=&quot;#确认-kubectl-连到-minikube&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;current-context&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nodes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;正常情况下会看到：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;使用 minikube 内部 Docker&lt;a href=&quot;#使用-minikube-内部-docker&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本地构建镜像后，如果希望 Kubernetes 直接使用这个镜像，需要让当前 shell 的 Docker 命令指向 minikube 内部 Docker：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;eval&lt;/span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker-env&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;之后构建的镜像会进入 minikube，可以配合：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;imagePullPolicy&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;IfNotPresent&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;避免 Kubernetes 去远程镜像仓库拉取。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;退出 minikube Docker 环境&lt;a href=&quot;#退出-minikube-docker-环境&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;eval&lt;/span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker-env&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-u&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;常用调试命令&lt;a href=&quot;#常用调试命令&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dashboard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ls&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;本地练习&lt;a href=&quot;#本地练习&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;推荐流程：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;eval&lt;/span&gt;&lt;span&gt; $(&lt;/span&gt;&lt;span&gt;minikube&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker-env&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;make&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build-base-image&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;APP_VERSION&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker-compose.yaml&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;user-api&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;admin-api&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;worker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image-worker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tag&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;user-api:dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localhost/user-api:dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-k&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deploy/overlay/dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;相关笔记：kubectl 常用命令&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Docker 镜像构建上下文</title><link>https://blog.81vm3.xyz/posts/docker-build-context/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/docker-build-context/</guid><description>docker build 末尾那个点是什么：构建上下文的作用、传输机制与控制范围。</description><pubDate>Thu, 15 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;如果注意,会看到 docker build命令最后有一个 &lt;code&gt;.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?&lt;/p&gt;
&lt;p&gt;这就引入了上下文的概念&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;提供构建时所需文件&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;COPY&lt;/code&gt;、&lt;code&gt;ADD&lt;/code&gt; 指令引用的文件路径都必须在上下文内。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;传输给 Docker daemon&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;在 &lt;code&gt;docker build&lt;/code&gt; 时，CLI 会把上下文打包成一个 tar 包，发送给后端守护进程。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;控制构建范围&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;若不小心把整个大目录（如 &lt;code&gt;/&lt;/code&gt; 或 &lt;code&gt;~&lt;/code&gt;）作为上下文，会严重拖慢构建。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section&gt;&lt;h2&gt;一个具体例子&lt;a href=&quot;#一个具体例子&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 上下文 = 当前目录（末尾的 .），Dockerfile 默认为 ./Dockerfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-app&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 上下文 = 当前目录，但指定别的 Dockerfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;microservice.Dockerfile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-app&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 上下文 = 指定目录（构建时路径都相对它解析）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-app&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./backend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;执行 &lt;code&gt;docker build .&lt;/code&gt; 时终端里那一行 &lt;code&gt;Sending build context to Docker daemon  xx MB&lt;/code&gt;，就是把整个上下文目录打包成 tar 传给 daemon 的过程——这也解释了为什么 &lt;code&gt;COPY&lt;/code&gt; 不能引用上下文之外的路径（如 &lt;code&gt;COPY ../foo&lt;/code&gt; 是非法的）。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;用 .dockerignore 收窄上下文&lt;a href=&quot;#用-dockerignore-收窄上下文&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;上下文太大不仅拖慢构建，还会把不该进镜像的文件传进 daemon。在上下文根目录放 &lt;code&gt;.dockerignore&lt;/code&gt;：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;.git&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;node_modules&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dist&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;*.log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;.env&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;语法类似 &lt;code&gt;.gitignore&lt;/code&gt;。被排除的文件不会进入 tar 包，&lt;code&gt;COPY .&lt;/code&gt; 也就拿不到它们，同时避免密钥、构建产物意外进镜像。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Kafka 的分区与副本机制</title><link>https://blog.81vm3.xyz/posts/kafka/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/kafka/</guid><description>Kafka Broker/Topic/分区的关系，以及 leader-follower 副本的读写与冗余备份机制。</description><pubDate>Fri, 09 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在 Kafka 中，每个 Kafka 实例称为 Broker，每个 Broker 中可以保存多个 Topic。每个 Topic 可以划分为多个分区，**每个分区保存的数据是不一样的，**这些分区可以在同一个 Broker 中，也可以在散布在不同的 Broker 中。&lt;/p&gt;
&lt;p&gt;一个 Broker 可以存储不同 Topic 的不同分区，也可以存储同一个 Topic 的不同分区。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;Pasted image 20260701172445.png&quot; loading=&quot;lazy&quot; width=&quot;725&quot; height=&quot;359&quot; src=&quot;/_astro/pasted-image-20260701172445.B6CfFkqE_Z2qfDRX.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20260701172445.png&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;分区与复制&lt;a href=&quot;#分区与复制&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;主题的每个分区都有至少一个副本，也就是 &lt;code&gt;--replication-factor&lt;/code&gt; 参数必须大于 1。副本分为 leader 和 follower 两种，每个副本都需要消耗一个存储空间，leader 对外提供读写消息，而 follower 提供冗余备份，leader 会及时将消息增量同步到所有 follower 中。&lt;/p&gt;&lt;p&gt;在 &lt;code&gt;hello-topic&lt;/code&gt; 主题中，当分区只有一个副本时，或只关注 leader 副本时，leader 副本对应的 Broker 节点位置如下：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;Pasted image 20260701173450.png&quot; loading=&quot;lazy&quot; width=&quot;827&quot; height=&quot;250&quot; src=&quot;/_astro/pasted-image-20260701173450.4bYNsgkA_Mv0H6.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20260701173450.png&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;如果设置了多个副本( &lt;code&gt;--replication-factor=3&lt;/code&gt; ) 时，leader 副本和 follower 副本的位置如下所示：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;Pasted image 20260701173500.png&quot; loading=&quot;lazy&quot; width=&quot;822&quot; height=&quot;256&quot; src=&quot;/_astro/pasted-image-20260701173500.C4N6LXIe_73geE.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20260701173500.png&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;在不同的副本中，只有 leader 副本能够进行读写，follower 接收从 leader 推送过来的数据，做好冗余备份。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;Pasted image 20260701173509.png&quot; loading=&quot;lazy&quot; width=&quot;766&quot; height=&quot;548&quot; src=&quot;/_astro/pasted-image-20260701173509.CFCDmKv3_Z29bIFu.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20260701173509.png&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img alt=&quot;Pasted image 20260701173520.png&quot; loading=&quot;lazy&quot; width=&quot;939&quot; height=&quot;493&quot; src=&quot;/_astro/pasted-image-20260701173520.C5DaTBdd_Z64ej1.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20260701173520.png&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Docker 镜像的分层与构建</title><link>https://blog.81vm3.xyz/posts/docker-image/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/docker-image/</guid><description>Docker 镜像的分层结构、UnionFS 与构建缓存机制，以及 docker build 的多种用法。</description><pubDate>Mon, 05 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h3&gt;🧱 镜像（Image）&lt;a href=&quot;#-镜像image&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;是一个 &lt;strong&gt;只读模板&lt;/strong&gt;，包含了运行应用所需的一切：操作系统、程序代码、依赖、配置等。&lt;/li&gt;
&lt;li&gt;它就像一份快照，可以重复使用。&lt;/li&gt;
&lt;li&gt;构建一次，可以启动很多个容器。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Docker 镜像是由多层构成的，每一层通常是只读的。这些层通过 UnionFS (联合文件系统) 组合在一起形成一个完整的文件系统，最终在容器运行时添加一个最上面的 &lt;strong&gt;可写层（writeable layer）&lt;/strong&gt;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;如果你改变了 Dockerfile 中的一层指令（如 &lt;code&gt;RUN&lt;/code&gt;、&lt;code&gt;COPY&lt;/code&gt;、&lt;code&gt;ADD&lt;/code&gt;），那么它之后的所有层都会重新构建&lt;/strong&gt;。这是 Docker 的构建缓存（build cache）机制所决定的。&lt;/p&gt;&lt;p&gt;如果多个命令都指向同一个目的，那么应该用一个run来进行，而不是叠加多层&lt;/p&gt;&lt;p&gt;用一个RUN：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; debian:jessie&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;RUN&lt;/span&gt;&lt;span&gt; buildDeps=&lt;/span&gt;&lt;span&gt;&apos;gcc libc6-dev make&apos;&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; apt-get update \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; apt-get install -y $buildDeps \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; wget -O redis.tar.gz &lt;/span&gt;&lt;span&gt;&quot;http://download.redis.io/releases/redis-3.2.5.tar.gz&quot;&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; mkdir -p /usr/src/redis \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; make -C /usr/src/redis \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; make -C /usr/src/redis install \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/* \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; rm redis.tar.gz \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; rm -r /usr/src/redis \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;amp;&amp;amp; apt-get purge -y --auto-remove $buildDeps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;docker build 各种用法&lt;a href=&quot;#docker-build-各种用法&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;从dockerfile&lt;a href=&quot;#从dockerfile&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;microservice.Dockerfile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker-jar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;minecraft-modpack-server&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;从标准输入&lt;a href=&quot;#从标准输入&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Dockerfile&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;从Git repo&lt;a href=&quot;#从git-repo&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://github.com/twang2218/gitlab-ce-zh.git#:8.14&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Docker 指令&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;删除镜像&lt;a href=&quot;#删除镜像&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 删除单个镜像（可以用镜像名:tag 或镜像 ID）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rmi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nginx:latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 强制删除（即使有基于它的容器存在）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rmi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;image-id&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 清理所有悬空镜像（dangling，即没有 tag 引用的中间层）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;prune&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 清理所有未被任何容器使用的镜像&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;prune&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;</content:encoded></item><item><title>本地负缓存</title><link>https://blog.81vm3.xyz/posts/local-negative-cache/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/local-negative-cache/</guid><description>把不存在/失败的查询结果缓存在本地内存中，短时间内直接返回，避免重复打到下游系统。</description><pubDate>Wed, 03 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;把不存在/失败结果缓存在本地内存里，短时间内直接返回，避免重复访问下游系统。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;id=999999 不存在 → 缓存 60 秒&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;后面 60 秒：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;直接返回不存在，不用查 DB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;section&gt;&lt;h2&gt;为什么需要&lt;a href=&quot;#为什么需要&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;典型的缓存只缓存「查到了」的结果，但线上更耗资源的往往是&lt;strong&gt;查不到&lt;/strong&gt;的请求：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;缓存穿透：不存在的 key 每次都要打到数据库，负面结果不缓存，等于每次都白查一遍。&lt;/li&gt;
&lt;li&gt;下游故障放大：某个依赖超时/报错后，上层不断重试同样的失败请求，把故障放大。&lt;/li&gt;
&lt;li&gt;恶意或爬虫流量：大量轮询不存在的资源 ID。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;负缓存（negative caching）就是把「不存在 / 失败」也当成一种结果缓存起来，短时间内对同一 key 直接复用这个结论。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;实现要点&lt;a href=&quot;#实现要点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 极简示意：本地 map + 过期时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;negativeCache&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Map&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// key -&amp;gt; expireAt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GetProfile&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Profile&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;negativeCache&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Load&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Now&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;Before&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;exp&lt;/span&gt;&lt;span&gt;.(&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Time&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ErrNotFound&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 命中负缓存，直接返回&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;repo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;errors&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Is&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ErrNotFound&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;negativeCache&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Store&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Now&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;Add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;60&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Second&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TTL 要短&lt;/strong&gt;：负缓存是「暂时的结论」，实体可能随后就被创建。一般秒级到一分钟，宁短勿长。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;只缓存确定性失败&lt;/strong&gt;：&lt;code&gt;不存在&lt;/code&gt; 可以缓存；&lt;code&gt;超时/网络错误&lt;/code&gt; 不应该固化为负缓存，否则下游恢复后仍被挡住。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;要有容量上限与淘汰&lt;/strong&gt;：本地内存是无底洞风险，配合 LRU 或分片 + 定期清理，防止被不存在的 key 撑爆。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;命中打点&lt;/strong&gt;：监控负缓存命中率，异常升高往往意味着上游调用方在犯错或有攻击流量。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;与「缓存空对象」是同一个思路，只是把空值判断从 Redis 前移到进程内，省一次网络往返。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>MySQL 索引与慢查询优化</title><link>https://blog.81vm3.xyz/posts/mysql-index-optimization/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/mysql-index-optimization/</guid><description>慢查询 200ms 阈值、JOIN 对数据量的影响、IN 列表过大丢索引与分批查询。</description><pubDate>Fri, 14 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;每条查询的时间应该控制在200ms内
否则认为是慢查询&lt;/p&gt;
&lt;p&gt;慢查询带来的后果是：IO开销过大，锁持有时间增加，导致数据库吞吐量降低&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;排查与定位&lt;a href=&quot;#排查与定位&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;开启慢查询日志：&lt;code&gt;slow_query_log=ON&lt;/code&gt;，&lt;code&gt;long_query_time=0.2&lt;/code&gt;，配合 &lt;code&gt;pt-query-digest&lt;/code&gt; 或云监控聚合分析。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;EXPLAIN&lt;/code&gt; 看执行计划，重点看 &lt;code&gt;type&lt;/code&gt;（至少到 &lt;code&gt;range&lt;/code&gt;，避免 &lt;code&gt;ALL&lt;/code&gt; 全表扫描）、&lt;code&gt;key&lt;/code&gt;（实际用到的索引）、&lt;code&gt;rows&lt;/code&gt;（预估扫描行数）、&lt;code&gt;Extra&lt;/code&gt;（&lt;code&gt;Using filesort&lt;/code&gt; / &lt;code&gt;Using temporary&lt;/code&gt; 都是危险信号）。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;JOIN 与数据量&lt;a href=&quot;#join-与数据量&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;内联JOIN是求交集，数据变小&lt;/p&gt;&lt;p&gt;外JOIN，会导致数据量过大&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;JOIN 的驱动表尽量选过滤后结果集小的那张，被驱动表的关联列必须有索引。&lt;/li&gt;
&lt;li&gt;避免在 JOIN 条件列上做函数运算或类型转换（如字符串列和数字比较），否则索引失效。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;索引失效的常见场景&lt;a href=&quot;#索引失效的常见场景&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;对索引列使用函数或运算：&lt;code&gt;WHERE DATE(created_at) = ...&lt;/code&gt;、&lt;code&gt;WHERE id + 1 = ...&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;隐式类型转换：varchar 列用数字比较。&lt;/li&gt;
&lt;li&gt;前导模糊匹配：&lt;code&gt;LIKE &apos;%keyword&apos;&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;联合索引不满足最左前缀。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IN 列表过大&lt;/strong&gt;：如果 IN 关键字包含的id过多，数据库有可能抛弃索引直接进行全表扫描（优化器认为回表成本高于全表扫描）。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;分批查询&lt;a href=&quot;#分批查询&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;如果单次查询的数据量大于1000，则最好需要分批次进行查询
每批次500条&lt;/p&gt;&lt;p&gt;分批不只为了保护索引，还能控制单次网络包大小、减少锁持有时间与内存占用。配合覆盖索引（只 SELECT 需要的列）效果更好。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Redis 数据持久化（RDB）</title><link>https://blog.81vm3.xyz/posts/redis-persistence/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/redis-persistence/</guid><description>Redis RDB 快照机制、save/bgsave 的阻塞差异、自动触发时机与 flushall 的覆盖语义。</description><pubDate>Tue, 28 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Redis 提供 2 种持久化方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RDB   将在内存中的数据库记录定期生成快照存入磁盘中&lt;/li&gt;
&lt;li&gt;AOF   将 Redis 的操作日志以追加的方式写入文件，&lt;/li&gt;
&lt;/ul&gt;
&lt;section&gt;&lt;h2&gt;RDB&lt;a href=&quot;#rdb&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;RedisDatabase&lt;/p&gt;&lt;p&gt;将Redis某一时刻的内存数据写入到RDB文件中，并保存到磁盘上。
该文件是一个&lt;strong&gt;压缩&lt;/strong&gt;过的&lt;strong&gt;二进制文件&lt;/strong&gt;，默认文件名为&lt;code&gt;dump.rdb&lt;/code&gt;，通过该文件可以还原redis数据库的数据。在Redis服务器启动时，会重新加载dump.rdb文件的数据到内存当中，达到恢复数据目的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;可根据&lt;/strong&gt; redis.conf &lt;strong&gt;配置文件中设置rdb文件名 和 保存目录：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 指定本地数据库文件名（rdb文件的名称），默认值为dump.rdb&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dbfilename dump.rdb&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 指定本地数据库存放目录（dump.rdb文件存放目录），rdb、aof文件也会写在这个目录dir /usr/local/var/db/redis/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;save&lt;a href=&quot;#save&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当某个客户端发送 save 命令后，此时会阻塞当前Redis服务器，在RDB文件创建完成之前是不能处理其他客户端发送的任何命令请求，如果数据量太大会造成长时间阻塞，期间redis无法处理其他请求，&lt;strong&gt;线上环境不建议使用&lt;/strong&gt;。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;bgsave&lt;a href=&quot;#bgsave&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当某个客户端发送 bgsave 命令后，Redis服务器会执行fork() 函数创建一个子进程，由子进程负责rdb文件创建和写入，期间服务器不会阻塞，可以接受其他客户端的命令请求，**但在fork执行阶段，服务器还会阻塞，无法接受其他客户端命令（一般时间很短）&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;自动触发&lt;a href=&quot;#自动触发&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在以下几种情况时会自动触发生成 RDB 文件：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;redis.conf&lt;/code&gt; 配置文件中达到 &lt;code&gt;save&lt;/code&gt; 参数条件&lt;/li&gt;
&lt;li&gt;主从复制时，从节点要从主节点进行全量复制，此时会触发 bgsave，生成快照发送到从节点&lt;/li&gt;
&lt;li&gt;执行 shutdown，如果没有开启 AOF 持久化，会触发 bgsave&lt;/li&gt;
&lt;li&gt;执行 flushall（生成空的 dump.rdb！）&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;flushall&lt;a href=&quot;#flushall&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt;flushall 生成的是空dump.rdb文件，目的是覆盖并删除上次备份的快照，防止redis重启时，自动载入并恢复到上一份备份数据！&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;</content:encoded></item><item><title>DDD 领域驱动设计入门</title><link>https://blog.81vm3.xyz/posts/ddd/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/ddd/</guid><description>DDD 的由来与核心概念：实体、值对象、聚合、仓储、分层架构与 Go 项目目录落地。</description><pubDate>Sat, 11 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;DDD（Domain-Driven Design，领域驱动设计）&lt;/strong&gt; 不是一种框架，而是一种&lt;strong&gt;面向复杂业务系统的软件设计方法论&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;它的核心思想是：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;软件结构应该围绕业务领域（Domain）组织，而不是围绕数据库、接口、框架组织。&lt;/p&gt;&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;section&gt;&lt;h1&gt;为什么会有 DDD&lt;a href=&quot;#为什么会有-ddd&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;很多项目一开始都是这样：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;controller&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;repository&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user_controller.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user_service.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user_repo.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;当业务简单时没问题。&lt;/p&gt;&lt;p&gt;但随着需求增加：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;用户&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;订单&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;支付&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;优惠券&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;库存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;物流&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;积分&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Service 会越来越大：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CreateOrder&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;检查库存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;检查优惠券&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;扣减库存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;创建订单&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;创建支付单&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;发MQ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;最后：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;OrderService&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;3000行&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;业务规则散落在：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Controller&lt;/li&gt;
&lt;li&gt;Service&lt;/li&gt;
&lt;li&gt;SQL&lt;/li&gt;
&lt;li&gt;MQ Consumer&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;维护起来很痛苦。&lt;/p&gt;&lt;p&gt;DDD 就是为了解决：&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;复杂业务逻辑如何长期演进。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;DDD 的核心概念&lt;a href=&quot;#ddd-的核心概念&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;1. Domain（领域）&lt;a href=&quot;#1-domain领域&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;领域就是业务范围。&lt;/p&gt;&lt;p&gt;例如电商：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;电商系统&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── 用户领域&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── 订单领域&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── 支付领域&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── 库存领域&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└── 物流领域&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;每个领域独立思考。&lt;/p&gt;&lt;p&gt;“这个东西如果脱离 HTTP、数据库、缓存、消息队列，仍然有业务意义吗？”&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;如果有，可能属于 domain&lt;/li&gt;
&lt;li&gt;如果没有，多半不属于 domain&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2. Entity（实体）&lt;a href=&quot;#2-entity实体&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;有唯一身份的对象。&lt;/p&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ID&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int64&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;即使名字变了：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;张三 → 李四&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;还是同一个用户。&lt;/p&gt;&lt;p&gt;因为：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ID没变&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;3. Value Object（值对象）&lt;a href=&quot;#3-value-object值对象&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;没有身份。&lt;/p&gt;&lt;p&gt;只关心值。&lt;/p&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Money&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Amount&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int64&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Currency&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;两个：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;100 CNY&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;100 CNY&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;就是相等的。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;4. Aggregate（聚合）&lt;a href=&quot;#4-aggregate聚合&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;DDD最重要概念之一。&lt;/p&gt;&lt;p&gt;例如订单：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Order&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── OrderItem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── Address&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└── PaymentInfo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这些对象一起维护一致性。&lt;/p&gt;&lt;p&gt;形成：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Order Aggregate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;section&gt;&lt;h3&gt;聚合根（Aggregate Root）&lt;a href=&quot;#聚合根aggregate-root&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;外部只能访问：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Order&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;不能直接改：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;OrderItem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;order&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AddItem&lt;/span&gt;&lt;span&gt;(...)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;而不是：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;order&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Items&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;Count&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这样业务规则集中。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;Repository&lt;a href=&quot;#repository&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Repository 不是 DAO。&lt;/p&gt;&lt;p&gt;DAO：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Create&lt;/span&gt;&lt;span&gt;(...)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Repository：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;OrderRepository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Save&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;order&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Order&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;FindByID&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;领域层不知道：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;MySQL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PostgreSQL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Redis&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;Domain Service&lt;a href=&quot;#domain-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;有些业务不属于某个实体。&lt;/p&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;订单创建&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;需要：&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;库存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;优惠券&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;支付&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;放进 Order 也不合适。&lt;/p&gt;&lt;p&gt;这时：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;OrderDomainService&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;负责跨聚合逻辑。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;Application Service&lt;a href=&quot;#application-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;很多人容易混淆。&lt;/p&gt;&lt;p&gt;DDD里通常：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Controller&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Application Service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Domain&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Repository&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Application Service：&lt;/p&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;例如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CreateOrder&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;cmd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CreateOrderCommand&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;order&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;domain&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;NewOrder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;order&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AddItem&lt;/span&gt;&lt;span&gt;(...)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;repo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Save&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;order&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Publish&lt;/span&gt;&lt;span&gt;(...)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;分层架构&lt;a href=&quot;#分层架构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;经典 DDD：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;┌──────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Presentation     │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Controller/API   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└────────┬─────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;▼&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;┌──────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Application      │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Use Case         │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└────────┬─────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;▼&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;┌──────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Domain           │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Entity           │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Aggregate        │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Domain Service   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└────────┬─────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;▼&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;┌──────────────────┐&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ Infrastructure   │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│ DB MQ Redis      │&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└──────────────────┘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;Go 项目常见目录&lt;a href=&quot;#go-项目常见目录&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;internal/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── application&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│   └── order&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│       └── service.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── domain&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│   └── order&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│       ├── entity.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│       ├── repository.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│       └── service.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├── infrastructure&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│   └── repository&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│       └── order_repo.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└── interfaces&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── http&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── order_handler.go&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;在微服务里怎么用&lt;a href=&quot;#在微服务里怎么用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;假设你之前说的在线判题系统：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gateway&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;problem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;judge&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sandbox&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;每个微服务都可以有自己的领域。&lt;/p&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;section&gt;&lt;h3&gt;problem-service&lt;a href=&quot;#problem-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Problem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Tag&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;SubmissionRule&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;judge-service&lt;a href=&quot;#judge-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Submission&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;JudgeTask&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;JudgeResult&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;user-service&lt;a href=&quot;#user-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;User&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Role&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Permission&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;DDD 和 MVC 的区别&lt;a href=&quot;#ddd-和-mvc-的区别&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;MVC：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Controller&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;DAO&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;关注：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;代码分层&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;p&gt;DDD：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Domain&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Aggregate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Business Rules&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;关注：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;业务建模&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;所以：&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;MVC 是技术视角，DDD 是业务视角。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;两者并不冲突。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;什么时候值得引入 DDD&lt;a href=&quot;#什么时候值得引入-ddd&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;如果是学习性质的：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Gateway&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;User&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Problem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Judge&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Sandbox&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;我的建议是：&lt;/p&gt;&lt;section&gt;&lt;h3&gt;第一阶段&lt;a href=&quot;#第一阶段&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;普通三层：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;handler&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;repo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;先把功能跑通。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;第二阶段&lt;a href=&quot;#第二阶段&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当出现：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;提交代码&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;创建Submission&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;发MQ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Judge消费&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;更新结果&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;更新排行榜&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这种复杂业务流时，&lt;/p&gt;&lt;p&gt;再引入：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Aggregate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Domain Service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Repository&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;会更容易体会 DDD 的价值。&lt;/p&gt;&lt;p&gt;否则很容易变成：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;为了DDD而DDD&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;写了很多目录和接口，但业务复杂度还没到那个程度。对于一个在线判题系统这类项目，比较合适的路线通常是：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;三层架构&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;理解微服务&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;事件驱动(MQ)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;DDD Lite&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;完整DDD&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这样学习曲线会平滑很多，也更符合实际项目的演进过程。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Python StrEnum 与 Literal 的区别</title><link>https://blog.81vm3.xyz/posts/python-strenum-literal/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/python-strenum-literal/</guid><description>StrEnum（运行时枚举）与 Literal（纯类型约束）的差异、对比表与 FastAPI/Pydantic 选型建议。</description><pubDate>Wed, 10 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;code&gt;StrEnum&lt;/code&gt; 和 &lt;code&gt;Literal&lt;/code&gt; 虽然都能限制字符串取值，但用途完全不同。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;1. StrEnum：运行时的枚举类型&lt;a href=&quot;#1-strenum运行时的枚举类型&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Python 3.11+&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; enum &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; StrEnum&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;StrEnum&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PENDING&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;pending&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;SUCCESS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;success&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;FAILED&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;failed&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;使用：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Status.&lt;/span&gt;&lt;span&gt;PENDING&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(status)          &lt;/span&gt;&lt;span&gt;# pending&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(status.value)    &lt;/span&gt;&lt;span&gt;# pending&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;特点：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;运行时真实存在的对象&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可以遍历&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;可以比较&lt;/li&gt;
&lt;li&gt;可以作为配置、数据库字段、API参数等统一定义&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; s &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; Status:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; status &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; Status.&lt;/span&gt;&lt;span&gt;PENDING&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;2. Literal：类型提示&lt;a href=&quot;#2-literal类型提示&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;来自 &lt;code&gt;typing&lt;/code&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; typing &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Literal&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Literal[&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;pending&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;success&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;failed&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;使用：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;update_status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Status&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;IDE 会提示：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;update_status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;pending&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;# ✅&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;update_status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;abc&quot;&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# ❌ 类型检查报错&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&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;li&gt;不能写 &lt;code&gt;Status.PENDING&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(Status)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;输出：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;typing.Literal[&lt;/span&gt;&lt;span&gt;&apos;pending&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;success&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;failed&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;对比&lt;a href=&quot;#对比&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;StrEnum&lt;/th&gt;&lt;th&gt;Literal&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;运行时存在&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;类型检查&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;可遍历&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;可作为常量&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;IDE 自动补全&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;一般&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JSON/API 参数约束&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;数据库存储映射&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;FastAPI/Pydantic 场景&lt;a href=&quot;#fastapipydantic-场景&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通常推荐：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; enum &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; StrEnum&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ModelProvider&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;StrEnum&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OPENAI&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;openai&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ANTHROPIC&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;anthropic&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;GEMINI&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;gemini&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pydantic &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; BaseModel&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Request&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;BaseModel&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;provider: ModelProvider&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;自动生成 OpenAPI：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;enum&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;openai&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;anthropic&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;gemini&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;同时还能：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; req.provider &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; ModelProvider.&lt;/span&gt;&lt;span&gt;OPENAI&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;什么时候用 Literal？&lt;a href=&quot;#什么时候用-literal&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当你只是想约束几个字符串参数，而且不会在别处复用：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;create_message&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;role&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Literal[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;user&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;system&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这种场景用 &lt;code&gt;Literal&lt;/code&gt; 很轻量。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;实际项目建议&lt;a href=&quot;#实际项目建议&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;业务领域概念（状态、模型提供商、订单类型等）&lt;/strong&gt; → &lt;code&gt;StrEnum&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;函数参数的简单约束&lt;/strong&gt; → &lt;code&gt;Literal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FastAPI/Pydantic Schema&lt;/strong&gt; → 优先 &lt;code&gt;StrEnum&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;很多大型 Python 项目（如 Pydantic、FastAPI、LangGraph 等）最终都会把重要的字符串常量抽成 &lt;code&gt;StrEnum&lt;/code&gt;，因为它既有类型安全，又有运行时能力。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Gin 模型绑定与验证</title><link>https://blog.81vm3.xyz/posts/gin-model-binding/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/gin-model-binding/</guid><description>Gin 的两类绑定方法（Must/Should）与 binding:&apos;required&apos; 字段校验用法。</description><pubDate>Tue, 02 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;使用时，需要在要绑定的所有字段上，设置相应的tag。 例如，使用 JSON 绑定时，设置字段标签为 &lt;code&gt;json:&quot;fieldname&quot;&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Gin提供了两类绑定方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Type&lt;/strong&gt; - Must bind
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Methods&lt;/strong&gt; - &lt;code&gt;Bind&lt;/code&gt;, &lt;code&gt;BindJSON&lt;/code&gt;, &lt;code&gt;BindXML&lt;/code&gt;, &lt;code&gt;BindQuery&lt;/code&gt;, &lt;code&gt;BindYAML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Behavior&lt;/strong&gt; - 这些方法属于 &lt;code&gt;MustBindWith&lt;/code&gt; 的具体调用。 如果发生绑定错误，则请求终止，并触发 &lt;code&gt;c.AbortWithError(400, err).SetType(ErrorTypeBind)&lt;/code&gt;。响应状态码被设置为 400 并且 &lt;code&gt;Content-Type&lt;/code&gt; 被设置为 &lt;code&gt;text/plain; charset=utf-8&lt;/code&gt;。 如果您在此之后尝试设置响应状态码，Gin会输出日志 &lt;code&gt;[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422&lt;/code&gt;。 如果您希望更好地控制绑定，考虑使用 &lt;code&gt;ShouldBind&lt;/code&gt; 等效方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type&lt;/strong&gt; - Should bind
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Methods&lt;/strong&gt; - &lt;code&gt;ShouldBind&lt;/code&gt;, &lt;code&gt;ShouldBindJSON&lt;/code&gt;, &lt;code&gt;ShouldBindXML&lt;/code&gt;, &lt;code&gt;ShouldBindQuery&lt;/code&gt;, &lt;code&gt;ShouldBindYAML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Behavior&lt;/strong&gt; - 这些方法属于 &lt;code&gt;ShouldBindWith&lt;/code&gt; 的具体调用。 如果发生绑定错误，Gin 会返回错误并由开发者处理错误和请求。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用 Bind 方法时，Gin 会尝试根据 Content-Type 推断如何绑定。 如果你明确知道要绑定什么，可以使用 &lt;code&gt;MustBindWith&lt;/code&gt; 或 &lt;code&gt;ShouldBindWith&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;你也可以指定必须绑定的字段。 如果一个字段的 tag 加上了 &lt;code&gt;binding:&quot;required&quot;&lt;/code&gt;，但绑定时是空值, Gin 会报错。&lt;/p&gt;
&lt;p&gt;如果结构体的某个字段本身也是一个结构体（嵌套结构体），为了正确验证，该结构体的字段也需要添加 &lt;code&gt;binding:&quot;required&quot;&lt;/code&gt; 标签。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 绑定 JSON&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Login&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`form:&quot;user&quot; json:&quot;user&quot; xml:&quot;user&quot;  binding:&quot;required&quot;`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;Password&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`form:&quot;password&quot; json:&quot;password&quot; xml:&quot;password&quot; binding:&quot;required&quot;`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Default&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 绑定 JSON ({&quot;user&quot;: &quot;manu&quot;, &quot;password&quot;: &quot;123&quot;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;POST&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/loginJSON&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Login&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ShouldBindJSON&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusBadRequest&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;error&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;()})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;manu&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Password&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;123&quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusUnauthorized&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;status&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;unauthorized&quot;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusOK&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;status&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;you are logged in&quot;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 绑定 XML (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;//  &amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;//  &amp;lt;root&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;//    &amp;lt;user&amp;gt;manu&amp;lt;/user&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;//    &amp;lt;password&amp;gt;123&amp;lt;/password&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;//  &amp;lt;/root&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;POST&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/loginXML&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Login&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ShouldBindXML&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusBadRequest&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;error&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;()})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;manu&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Password&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;123&quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusUnauthorized&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;status&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;unauthorized&quot;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusOK&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;status&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;you are logged in&quot;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 绑定 HTML 表单 (user=manu&amp;amp;password=123)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;POST&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/loginForm&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Login&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 根据 Content-Type Header 推断使用哪个绑定器。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ShouldBind&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusBadRequest&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;error&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Error&lt;/span&gt;&lt;span&gt;()})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;manu&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Password&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;123&quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusUnauthorized&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;status&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;unauthorized&quot;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;StatusOK&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;gin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;status&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;you are logged in&quot;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// 监听并在 0.0.0.0:8080 上启动服务&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;router&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;:8080&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;66&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded></item><item><title>Go 的 Small Interface 设计理念</title><link>https://blog.81vm3.xyz/posts/go-small-interface/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/go-small-interface/</guid><description>从编译模型看 Go 与 C++ 契约方式的差异：消费者定义小接口与隐式实现的哲学。</description><pubDate>Tue, 05 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;C++ 使用时必须依赖头文件声明接口，而 Go 却可以在消费端就地定义 interface，由类型隐式满足契约。&lt;strong&gt;这个差异的核心在于语言的设计哲学、实现机制和编译模型的不同。&lt;/strong&gt; Go 和 C++ 在“契约”（contract）定义方式上的对比，体现了两种完全不同的编程范式。&lt;/p&gt;
&lt;section&gt;&lt;h3&gt;1. C++ 的方式：生产者提供全局 Header 作为契约（显式、中心化）&lt;a href=&quot;#1-c-的方式生产者提供全局-header-作为契约显式中心化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;历史和编译模型驱动&lt;/strong&gt;：C++ 继承自 C 的&lt;strong&gt;分离编译（separate compilation）&lt;strong&gt;模型。源文件（.cpp）分开编译成对象文件，再链接。编译器在编译一个 .cpp 时，需要知道其他模块的&lt;/strong&gt;声明&lt;/strong&gt;（类型、函数签名、类布局等），否则无法生成正确的代码（尤其是虚函数表、内存布局等）。
&lt;ul&gt;
&lt;li&gt;Header 文件（.h/.hpp）就是这个“声明”的载体。它定义了类、函数、虚方法等，作为&lt;strong&gt;全局可见的契约&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;生产者（库作者）必须在 header 中把接口写好，消费者（用户代码）通过 &lt;code&gt;#include&lt;/code&gt; 来使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;显式实现&lt;/strong&gt;：类需要显式继承抽象基类（带纯虚函数），或使用模板。改变 header 往往影响 ABI（二进制兼容性），容易导致“header hell”、编译时间爆炸和耦合。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优势&lt;/strong&gt;：适合大型系统，需要精确控制内存布局、性能和二进制接口（比如游戏引擎、系统库）。header 像一份“公开规格书”。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这是&lt;strong&gt;生产者驱动&lt;/strong&gt;（producer-driven）的契约：生产者决定“我的东西长什么样，你们都得按这个来”。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;2. Go 的方式：消费者在消费端定义 interface（隐式、分散化）&lt;a href=&quot;#2-go-的方式消费者在消费端定义-interface隐式分散化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;编译模型不同&lt;/strong&gt;：Go &lt;strong&gt;没有 header&lt;/strong&gt;，整个 package 一起编译（快速构建是 Go 的核心目标之一）。编译器能直接看到所有源码，不需要单独的声明文件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隐式满足（Implicit Implementation）&lt;/strong&gt;：这是 Go 接口最关键的特性。
&lt;ul&gt;
&lt;li&gt;一个类型只要实现了 interface 声明的所有方法，就&lt;strong&gt;自动满足&lt;/strong&gt;该 interface，不需要 &lt;code&gt;implements&lt;/code&gt; 关键字。&lt;/li&gt;
&lt;li&gt;接口本身只是&lt;strong&gt;一组方法签名&lt;/strong&gt;的集合（往往很小，比如 &lt;code&gt;io.Reader&lt;/code&gt; 只一个 &lt;code&gt;Read&lt;/code&gt; 方法）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;消费者定义&lt;/strong&gt;：推荐在&lt;strong&gt;使用接口的地方&lt;/strong&gt;（消费者包）定义 interface，而不是在提供具体实现的包里。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;为什么 Go 这样设计？&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;解耦和灵活性&lt;/strong&gt;：生产者只需提供&lt;strong&gt;具体类型&lt;/strong&gt;（struct + 方法），不需要预知所有可能的用法。消费者根据自己&lt;strong&gt;当前需求&lt;/strong&gt;定义最小化的 interface（“我只需要这些行为”）。这符合 Go “小接口、大组合”的哲学（Small Interfaces）。
&lt;ul&gt;
&lt;li&gt;例子：标准库的 &lt;code&gt;io.Reader&lt;/code&gt;、&lt;code&gt;io.Writer&lt;/code&gt;、&lt;code&gt;fmt.Stringer&lt;/code&gt; 等，都是极小的接口，定义在需要它们的地方。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;减少依赖&lt;/strong&gt;：消费者定义 interface 时，不需要导入生产者包里的接口定义（避免循环依赖或不必要的包依赖）。测试时特别方便——你可以轻松 mock 一个只满足你自定义 interface 的假对象。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Duck Typing 的静态检查版&lt;/strong&gt;：像动态语言的鸭子类型，但编译期就检查。生产者代码不需要“知道”任何 interface 的存在。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设计哲学&lt;/strong&gt;：Go 强调&lt;strong&gt;简单、可维护、少预判&lt;/strong&gt;。生产者不用在设计时“预见所有用例”（这往往会导致胖接口、违背接口隔离原则）。消费者只依赖自己真正需要的行为，代码更松耦合、更易演化。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;总结对比&lt;a href=&quot;#总结对比&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方面&lt;/th&gt;&lt;th&gt;C++ (Header)&lt;/th&gt;&lt;th&gt;Go (Interface)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;谁定义契约&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;生产者（全局 header）&lt;/td&gt;&lt;td&gt;消费者（使用处定义）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;实现方式&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;显式（继承、声明）&lt;/td&gt;&lt;td&gt;隐式（只要有方法就行）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;接口大小&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;倾向较大、完整类接口&lt;/td&gt;&lt;td&gt;极小、单一职责（one-method 常见）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;耦合度&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;较高（header 变更影响大）&lt;/td&gt;&lt;td&gt;极低&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;适用场景&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;性能敏感、大型系统、ABI 稳定&lt;/td&gt;&lt;td&gt;微服务、快速迭代、测试友好&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;根本原因&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;分离编译 + 历史传统&lt;/td&gt;&lt;td&gt;统一编译 + 现代简约哲学&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;strong&gt;Go 的这种设计不是“随意”，而是深思熟虑的结果&lt;/strong&gt;：它让接口真正成为“行为契约”而非“类型层次结构”。很多从 Java/C++ 转 Go 的人初期会不适应（总想在生产者端定义大接口），但用熟后会发现测试、扩展和维护都轻松很多。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>CMake：add_subdirectory 与 add_library 的区别</title><link>https://blog.81vm3.xyz/posts/cmake-add-subdirectory-vs-add-library/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/cmake-add-subdirectory-vs-add-library/</guid><description>add_subdirectory、add_library 与 target_link_libraries 各自的职责边界。</description><pubDate>Tue, 15 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you want to compile the code into your project directly, that’s not a library, that’s just code.&lt;/p&gt;
&lt;p&gt;A library is a distinct compiled and linked object. A static library is a &lt;code&gt;.a&lt;/code&gt;/&lt;code&gt;.lib&lt;/code&gt; file, a shared library is a &lt;code&gt;.so&lt;/code&gt;/&lt;code&gt;.dll&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;If you just want to add source code files to your current target, you do so with &lt;code&gt;target_sources()&lt;/code&gt; and that’s it. No need to create a library at all.&lt;/p&gt;
&lt;p&gt;So with that in mind, we can now talk about the commands:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;add_subdirectory()&lt;/code&gt;: This has nothing to do with libraries, this just runs the CML of a subdirectory. The code in that CML can do anything, maybe it creates a library, maybe it adds source code files to your current project, maybe it plays a little song and prints messages to your build log&lt;/p&gt;
&lt;p&gt;&lt;code&gt;add_library()&lt;/code&gt;: This creates a new library target, a new &lt;code&gt;.lib&lt;/code&gt; or &lt;code&gt;.dll&lt;/code&gt; file to be compiled and linked. It is the sister command to &lt;code&gt;add_executable()&lt;/code&gt;, which creates a new binary executable target (&lt;code&gt;.exe&lt;/code&gt; on Windows)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;target_link_libraries()&lt;/code&gt;: This links a library, maybe created in your current project or maybe an imported library from &lt;code&gt;find_package()&lt;/code&gt;/&lt;code&gt;find_library()&lt;/code&gt;, into a target&lt;/p&gt;</content:encoded></item><item><title>CMake target_include_directories 的三种作用域</title><link>https://blog.81vm3.xyz/posts/cmake-target-include-directories/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/cmake-target-include-directories/</guid><description>target_include_directories 的 PRIVATE/INTERFACE/PUBLIC 语义、适用场景与对照表。</description><pubDate>Tue, 08 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h2&gt;&lt;code&gt;target_include_directories()&lt;/code&gt;&lt;a href=&quot;#target_include_directories&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;命令可以为目标指定包含目录，并且可以使用 &lt;strong&gt;&lt;code&gt;PRIVATE&lt;/code&gt;&lt;/strong&gt;、&lt;strong&gt;&lt;code&gt;INTERFACE&lt;/code&gt;&lt;/strong&gt; 或 &lt;strong&gt;&lt;code&gt;PUBLIC&lt;/code&gt;&lt;/strong&gt; 来控制这些包含目录的作用范围以及它们是否会传播给其他依赖该目标的目标。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;1. &lt;code&gt;PRIVATE&lt;/code&gt;&lt;a href=&quot;#1-private&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;PRIVATE&lt;/code&gt; 意味着包含目录&lt;strong&gt;仅对该目标自身&lt;/strong&gt;可见，它不会传播给链接该目标的其他目标。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;target_include_directories&lt;/span&gt;&lt;span&gt;(MyTarget PRIVATE include/)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;：目标在自身编译时需要该包含目录，但不希望其他链接到这个目标的目标使用该目录。&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. &lt;code&gt;INTERFACE&lt;/code&gt;&lt;a href=&quot;#2-interface&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;INTERFACE&lt;/code&gt; 表示该目标本身&lt;strong&gt;不需要&lt;/strong&gt;这个包含目录，但是&lt;strong&gt;链接到这个目标的其他目标&lt;/strong&gt;会需要它。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;target_include_directories&lt;/span&gt;&lt;span&gt;(MyTarget INTERFACE include/)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;：该目标是一个头文件库（例如header-only library），它自身不需要包含目录，但任何链接到它的目标都需要这个包含目录来编译。&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. &lt;code&gt;PUBLIC&lt;/code&gt;&lt;a href=&quot;#3-public&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;PUBLIC&lt;/code&gt; 意味着包含目录对该目标&lt;strong&gt;自身&lt;/strong&gt;和&lt;strong&gt;链接到该目标的其他目标&lt;/strong&gt;都可见。它既会用于编译这个目标，也会传播给任何依赖它的其他目标。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;target_include_directories&lt;/span&gt;&lt;span&gt;(MyTarget PUBLIC include/)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;：该目标在编译时需要包含目录，同时任何依赖这个目标的其他目标也需要该包含目录。&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;总结：&lt;a href=&quot;#总结&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;可见性&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;目标本身使用&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;链接到该目标的其他目标使用&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PRIVATE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;INTERFACE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PUBLIC&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;</content:encoded></item><item><title>Go 的 map</title><link>https://blog.81vm3.xyz/posts/go-map/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/go-map/</guid><description>Go map 的引用类型本质、key 的约束、nil 行为与初始化示例。</description><pubDate>Fri, 20 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;code&gt;map&lt;/code&gt; 是引用类型，可以使用如下&lt;strong&gt;声明&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;map 不是”简单结构”，是复杂的引用类型，必须 &lt;code&gt;make&lt;/code&gt; 分配底层哈希表内存。&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;map1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;keytype&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;valuetype&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;map1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;在声明的时候不需要知道 &lt;code&gt;map&lt;/code&gt; 的长度，&lt;code&gt;map&lt;/code&gt; 是可以动态增长的。&lt;/p&gt;
&lt;p&gt;未初始化的 &lt;code&gt;map&lt;/code&gt; 的值是 &lt;code&gt;nil&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;key 可以是任意可以用 &lt;code&gt;==&lt;/code&gt; 或者 &lt;code&gt;!=&lt;/code&gt; 操作符比较的类型，比如 &lt;code&gt;string&lt;/code&gt;、&lt;code&gt;int&lt;/code&gt;、&lt;code&gt;float32(64)&lt;/code&gt;。所以数组、切片和结构体不能作为 key (译者注：含有数组切片的结构体不能作为 key，只包含内建类型的 &lt;code&gt;struct&lt;/code&gt; 是可以作为 key 的），但是指针和接口类型可以。如果要用结构体作为 key 可以提供 &lt;code&gt;Key()&lt;/code&gt; 和 &lt;code&gt;Hash()&lt;/code&gt; 方法，这样可以通过结构体的域计算出唯一的数字或者字符串的 key。&lt;/p&gt;
&lt;p&gt;value 可以是任意类型的；通过使用空接口类型（详见&lt;a href=&quot;https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/11.9.md&quot; target=&quot;_blank&quot;&gt;第 11.9 节&lt;/a&gt;），我们可以存储任意值，但是使用这种类型作为值时需要先做一次类型断言（详见&lt;a href=&quot;https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/11.3.md&quot; target=&quot;_blank&quot;&gt;第 11.3 节&lt;/a&gt;）。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;fmt&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mapLit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;//var mapCreated map[string]float32&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mapAssigned&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mapLit&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;one&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;two&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mapCreated&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;make&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;float32&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mapAssigned&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;mapLit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mapCreated&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;key1&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;4.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mapCreated&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;key2&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;3.14159&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mapAssigned&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;two&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Map literal at &lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;one&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt; is: &lt;/span&gt;&lt;span&gt;%d&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;mapLit&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;one&quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Map created at &lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;key2&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt; is: &lt;/span&gt;&lt;span&gt;%f&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;mapCreated&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;key2&quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Map assigned at &lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;two&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt; is: &lt;/span&gt;&lt;span&gt;%d&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;mapLit&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;two&quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Map literal at &lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;ten&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt; is: &lt;/span&gt;&lt;span&gt;%d&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;mapLit&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;ten&quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded></item><item><title>Wooden Toy Festival 题解：二分答案与贪心验证</title><link>https://blog.81vm3.xyz/posts/wooden-toy-festival/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/wooden-toy-festival/</guid><description>三个雕刻师制作 n 个玩具的最小等待时间：二分答案 + 排序后贪心分配验证，附完整 C++ 代码。</description><pubDate>Sun, 25 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h2&gt;题意：&lt;a href=&quot;#题意&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;有三个雕刻师，他们需要制作n个玩具，对于n个玩具，每个玩具都有一个图案值a[i]，&lt;/p&gt;&lt;p&gt;如果雕刻师选择的图案是 x ，那么为他制作一个图案为 y 的玩具需要 |x−y| 的时间，因为玩具越像他能立即制作的玩具，雕刻师的工作速度就越快。&lt;/p&gt;&lt;p&gt;雕刻师们都是非常熟练的人，可以同时处理不同玩具
雕刻师们希望在选择准备工作的样式时，尽可能减少完成制作所有玩具所需要的等待时间&lt;/p&gt;&lt;p&gt;要求你求出制作出所有玩家所需要的最短等待时间&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;分析&lt;a href=&quot;#分析&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当需要求某个数是最大值/最小值的时候，会考虑到问题是否可以通过二分搜索来解决。&lt;/p&gt;&lt;p&gt;能用二分搜索解决的问题通常具有单调性，而对于本题，很明显的一个事实是如果等待时间越短，那么三个雕刻师一开始所选择的图案就与越多的玩具的a[i]相似.。&lt;/p&gt;&lt;p&gt;而且，还注意到，如果3个雕刻师能够在 t 的时间内制作所有的玩具，那么3个雕刻师必定也能在 d (d &amp;gt; t) 的时间内也制作所有的玩具&lt;/p&gt;&lt;p&gt;因此我们可以尝试二分搜索可行的时间（即三个雕刻师是否可以在这个时间内把所有的玩具制作完），一旦查到可行的时间，我们便试着不断缩小搜索的区间去把mid值逼近最优解。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;条件判断&lt;a href=&quot;#条件判断&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;那么现在的问题是该如何判断三者可以在时间 t 内制作所有玩具？&lt;/p&gt;&lt;p&gt;想象一下，如果我们给三个雕刻师分别分配任务，时间 t 实际上取决于三者之间最晚完成任务的人。
考虑到任务分配的顺序是没有影响的，那么我们最好对图案数组先排序一次，因为排序后的数组中对于 任意的 (i, j)，他们的 |a[i] - a[j]| 的值总要比未排序的要小。&lt;/p&gt;&lt;p&gt;也就是因为这个排序后的性质，如果我们在排序后的数组里面按顺序分配任务，&lt;strong&gt;选定 i，某个雕刻师在 t 时间内能制作完成的玩具数量即为在 [a[i], a[i] + 2*x] 值区间内的 a[i] 的数量&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;所以剩下来的部分就只有模拟了，我们模拟分配工作给雕刻师，记录当前已完成制作的玩具的数量 cur，每名雕刻师的工作完成后cur都会增加，而这个cur后面的玩具又会交给下一个雕刻师，最后检查cur是否到达n个数量即可&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;详细代码&lt;a href=&quot;#详细代码&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;bits/stdc++.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;typedef&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;typedef&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pair&lt;/span&gt;&lt;span&gt;&amp;lt;int&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;mod&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;check&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cur&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;cur&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;cur&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;cur&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;cur&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;cur&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cur&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;solve&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mid&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;//mid为三者雕刻所需要的最大时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;//check的时候，尽可能多的在mid时间内为雕刻师安排多的v&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;//显然这个问题具有单调性，如果用时越久，模具的制作偏差就越大&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mid&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;check&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;mid&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mid&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mid&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mid&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;endl&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ios_base::&lt;/span&gt;&lt;span&gt;sync_with_stdio&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tie&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tie&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;solve&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;</content:encoded></item><item><title>CF 957E Novice&apos;s Mistake 题解</title><link>https://blog.81vm3.xyz/posts/cf957e-novices-mistake/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/cf957e-novices-mistake/</guid><description>字符串乘法与数字乘法结果相同的 (a,b) 计数：通过收紧枚举上下界让暴力可过。</description><pubDate>Sun, 09 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h2&gt;原题&lt;a href=&quot;#原题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;K1o0n 的第一个编程问题是这样的”Noobish_Monk有 n 个朋友。 (1≤n≤100) 个朋友。每个朋友都给了他 a (1≤a≤10000) 个苹果。 (1≤a≤10000) 个苹果作为生日礼物。收到这样的礼物后，诺比什/蒙克很高兴，他回赠了 b (1≤b≤min(10000,a⋅n)) 个苹果。 (1≤b≤min(10000,a⋅n)) 个苹果给他的朋友们。诺比西和尚还剩下多少个苹果？”&lt;/p&gt;&lt;p&gt;K1o0n 写了一个解决方案，但不小心把 n 的值看成了字符串，所以 n⋅a−b 的值的计算方法不同。具体来说&lt;/p&gt;&lt;p&gt;当用字符串 n 乘以整数 a 时，他将得到字符串
s=n+n+⋯+n+n (a times)
从字符串 s 中减去整数 b 时，将删除最后的 b 个字符。如果 b 大于或等于字符串 s 的长度，则字符串 s将变为空。
了解到这一点后，ErnKor 开始关注在给定的 n 中，有多少对 (a,b) 满足问题的约束条件，而 K1o0n 的解给出了正确答案。&lt;/p&gt;&lt;p&gt;“解法给出了正确答案 “意味着它输出了一个非空字符串，这个字符串转换成整数后等于正确答案，即 n⋅a−b 的值。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;输入&lt;a href=&quot;#输入&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;第一行包含一个整数 t ( 1≤t≤100) - 测试用例数。
对于每个测试用例，单行输入包含一个整数 n ( 1≤n≤100)。
保证在所有测试用例中， n 都是不同的。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;输出&lt;a href=&quot;#输出&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;对于每个测试用例，按以下格式输出答案：
在第一行，输出整数 x - 给定 n 的坏测试次数。
在接下来的 x 行中，输出两个整数 ai 和 bi - K1o0n 在测试” n “中的解决方案的整数。 ai bi” 得到正确答案。&lt;/p&gt;&lt;p&gt;Input&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Output&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;219&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;216&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;2218&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2214&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;165&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;162&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;1262&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2519&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;题目大意：&lt;a href=&quot;#题目大意&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;给你一个整数n，现在对于n*a - b有两种运算：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;n作为一个字符往后延伸至a个，然后从最后减去b个字符&lt;/li&gt;
&lt;li&gt;n作为一个数字，进行运算n*a - b&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;需要你求出 (a, b) 不同的组合数，使得两种运算后的结果相同。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;思考&lt;a href=&quot;#思考&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;此题的数据范围不大，使用暴力枚举再调整合适的枚举范围是可以通过的。&lt;/p&gt;&lt;p&gt;对于此题，我们容易想到O(n^2)的暴力解法，即从010000枚举a再从 0a*n 去枚举b
但是这样子做必定会超时，我们不可能直接按题目给的范围去直接枚举b&lt;/p&gt;&lt;section&gt;&lt;h4&gt;调整上界&lt;a href=&quot;#调整上界&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;由于在第一种操作中，减去b会使得n&lt;em&gt;a减去b个字符，结果的字符串字符数不可能为负数
因此b的上界即是n&lt;/em&gt;a的字符串的最长长度，即 |n|*a，即 数字n变成字符串后的长度再乘每次枚举的a&lt;/p&gt;&lt;p&gt;所以我们确定b的上界为  |n|*a&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;tmp&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tmp&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;&apos;0&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10000&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;调整下界&lt;a href=&quot;#调整下界&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;回到题目观察数据范围，我们发现n*a - b的范围是严格小于 10^6的，也就是说，按照第一种操作，字符串的长度最多不会超过6个字符，
于是下界minB的计算：|n|∗a−minB≤6
minB=|n|∗a−6&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;比较两种计算的值&lt;a href=&quot;#比较两种计算的值&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;十进制逐位加，注意一个小技巧：这里对arr下标取余运算，我们设arr是一个大小为3的数组，下标存的是 n 的每一位数字&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; //具体值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;span&gt; //目标的字符串有多长&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push_back&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;题解代码&lt;a href=&quot;#题解代码&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;bits/stdc++.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;typedef&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;typedef&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pair&lt;/span&gt;&lt;span&gt;&amp;lt;int&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;solve&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tmp&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;256&lt;/span&gt;&lt;span&gt;] {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;itoa&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;tmp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;tmp&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tmp&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;&apos;0&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10000&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;//对于B:  上界: a*len-1，下界: a*len-6 (在区间内最多不会超过6个字符)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;max&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; //具体值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;span&gt; //目标的字符串有多长&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;||&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push_back&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;endl&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos; &apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;endl&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ios_base::&lt;/span&gt;&lt;span&gt;sync_with_stdio&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tie&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tie&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;solve&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;66&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;</content:encoded></item><item><title>Tarjan 算法求强连通分量</title><link>https://blog.81vm3.xyz/posts/tarjan/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/tarjan/</guid><description>Tarjan 算法求强连通分量（SCC）的核心思路、dfn/low 更新规则、代码框架与缩点等常见应用。</description><pubDate>Sun, 12 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Tarjan 算法是一种用于 &lt;strong&gt;求强连通分量（SCC, Strongly Connected Components）&lt;/strong&gt; 的高效算法，时间复杂度 &lt;strong&gt;O(n + m)&lt;/strong&gt;，其中 &lt;span&gt;&lt;span&gt;nn&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 是顶点数，&lt;span&gt;&lt;span&gt;mm&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 是边数。它基于 &lt;strong&gt;深度优先搜索（DFS）&lt;/strong&gt;，使用&lt;strong&gt;回溯&lt;/strong&gt;的思想来判断一个点是否属于同一个 SCC。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;&lt;strong&gt;1. Tarjan 算法核心思路&lt;/strong&gt;&lt;a href=&quot;#1-tarjan-算法核心思路&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;时间戳（dfn）&lt;/strong&gt;：记录每个节点的 &lt;strong&gt;DFS 访问次序&lt;/strong&gt;，每个点的 dfn[u] 值是其访问顺序（从 1 开始递增）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最小可达值（low）&lt;/strong&gt;：记录 &lt;strong&gt;当前节点能通过 DFS 访问到的最早的节点&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;&lt;ul&gt;
&lt;li&gt;如果 low[u] == dfn[u]，说明 u 是一个 SCC 的根，栈中 u 及其上方的所有点属于同一 SCC。&lt;/li&gt;
&lt;/ul&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;栈（stack）&lt;/strong&gt;：维护 SCC，确保 SCC 内的点按拓扑顺序排列。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;入栈标记（in_stack）&lt;/strong&gt;：用于判断当前节点是否在栈中，避免重复计算。&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;&lt;strong&gt;2. Tarjan 代码框架&lt;/strong&gt;&lt;a href=&quot;#2-tarjan-代码框架&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;bits/stdc++.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt;  // 最大节点数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;int&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;graph&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;span&gt;   // 邻接表存储图&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dfn&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;ts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;scc_cnt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in_stack&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;stack&lt;/span&gt;&lt;span&gt;&amp;lt;int&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stk&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tarjan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;dfn&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;ts&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt;  // 设置访问次序&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;stk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;in_stack&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt; : &lt;/span&gt;&lt;span&gt;graph&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;dfn&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;span&gt;  // 递归访问&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;tarjan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;span&gt;  // 回溯更新 low 值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;in_stack&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;span&gt;  // 发现回边&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;dfn&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;dfn&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;low&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;span&gt;  // 发现 SCC 根&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;scc_cnt&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;top&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;stk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;pop&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;in_stack&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scc_cnt&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt;  // 给 SCC 赋编号&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;find_scc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;dfn&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;tarjan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;&lt;strong&gt;3. Tarjan SCC 代码详解&lt;/strong&gt;&lt;a href=&quot;#3-tarjan-scc-代码详解&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;&lt;strong&gt;(1) dfn[u] 和 low[u]&lt;/strong&gt;&lt;a href=&quot;#1-dfnu-和-lowu&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;dfn[u]：表示 &lt;strong&gt;访问次序&lt;/strong&gt;，用递增的时间戳标记。&lt;/li&gt;
&lt;li&gt;low[u]：表示 &lt;strong&gt;回溯能到的最早访问点&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更新规则&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;low[u] = min(low[u], low[v])（如果 v 是 u 的子节点）。
low[u] = min(low[u], dfn[v])（如果 v 已访问，且 v 在栈中）。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;&lt;strong&gt;(2) SCC 识别&lt;/strong&gt;&lt;a href=&quot;#2-scc-识别&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;如果 dfn[u] == low[u]，说明 u 是 SCC 根，栈中 u 及其上方的所有点属于同一 SCC。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SCC 出栈的顺序即拓扑序&lt;/strong&gt;，可以用于 &lt;strong&gt;缩点（Condensation Graph）&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;&lt;strong&gt;4. SCC 相关应用&lt;/strong&gt;&lt;a href=&quot;#4-scc-相关应用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;&lt;strong&gt;(1) 求缩点 DAG&lt;/strong&gt;&lt;a href=&quot;#1-求缩点-dag&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;SCC 形成后，我们可以 &lt;strong&gt;建立一个新的 DAG&lt;/strong&gt;（有向无环图），以 SCC 为点，SCC 之间有向边：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;int&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scc_graph&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;span&gt;  // SCC 缩点后的图&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;scc_in_degree&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;span&gt;  // SCC 入度&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build_scc_graph&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt; : &lt;/span&gt;&lt;span&gt;graph&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;]) {&lt;/span&gt;&lt;span&gt;  // 仅当 u, v 属于不同 SCC 时建边&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;scc_graph&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span&gt;]].&lt;/span&gt;&lt;span&gt;push_back&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;scc_in_degree&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;&lt;strong&gt;(2) 统计有向图中的「强连通块」&lt;/strong&gt;&lt;a href=&quot;#2-统计有向图中的强连通块&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Tarjan 算法可以用于求解 &lt;strong&gt;一个图最多能划分成多少个强连通块&lt;/strong&gt;：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;图的强连通分量个数: &quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scc_cnt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;endl&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;&lt;strong&gt;(3) 计算入度为 0 的 SCC 数量&lt;/strong&gt;&lt;a href=&quot;#3-计算入度为-0-的-scc-数量&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;入度为 0 的 SCC &lt;strong&gt;在缩点 DAG 中没有前驱&lt;/strong&gt;，可用于拓扑排序：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zero_in_degree_scc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scc_cnt&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;scc_in_degree&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;zero_in_degree_scc&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;&lt;strong&gt;(4) 计算强连通分量中的最小代价&lt;/strong&gt;&lt;a href=&quot;#4-计算强连通分量中的最小代价&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;有时 SCC 内有一些数值（如贿赂代价、最小值等），可以用 &lt;strong&gt;SCC 合并后取最小值&lt;/strong&gt;：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;scc_min_cost&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;scc_cnt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;INF&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;scc_min_cost&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;scc_min_cost&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;scc_id&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]], &lt;/span&gt;&lt;span&gt;cost&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;&lt;strong&gt;5. 复杂度分析&lt;/strong&gt;&lt;a href=&quot;#5-复杂度分析&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tarjan 的时间复杂度&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;每个点 &lt;strong&gt;被访问 1 次&lt;/strong&gt;（O(n)）。
每条边 &lt;strong&gt;被遍历 1 次&lt;/strong&gt;（O(m)）。
&lt;strong&gt;总时间复杂度 O(n + m)&lt;/strong&gt;，适用于 &lt;strong&gt;大规模数据&lt;/strong&gt;（如 &lt;span&gt;&lt;span&gt;n,m≤105n, m \leq 10^5&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;≤&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;）。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>0-1 背包问题</title><link>https://blog.81vm3.xyz/posts/knapsack-01/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/knapsack-01/</guid><description>0-1 背包的状态定义、二维 DP 转移方程与一维滚动数组空间优化。</description><pubDate>Sun, 15 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;题意概要：有 n 个物品和一个容量为 W 的背包，每个物品有重量 w_{i} 和价值 v_{i} 两种属性，要求选若干物品放入背包使背包中物品的总价值最大且背包中物品的总重量不超过背包的容量。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;在上述例题中，由于每个物体只有两种可能的状态（取与不取），对应二进制中的 &lt;span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 和 &lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，这类问题便被称为「0-1 背包问题」。&lt;/p&gt;
&lt;p&gt;例题中已知条件有第 i 个物品的重量 w_{i}，价值 v_{i}，以及背包的总容量 W。
设 DP 状态 f_{i,j} 为在只能放前 i 个物品的情况下，容量为 j 的背包所能达到的最大总价值。&lt;/p&gt;
&lt;p&gt;考虑转移。假设当前已经处理好了前 i-1 个物品的所有状态，那么对于第 i 个物品，当其不放入背包时，背包的剩余容量不变，背包中物品的总价值也不变，故这种情况的最大价值为 f_{i-1,j}；当其放入背包时，背包的剩余容量会减小 w_{i}，背包中物品的总价值会增大 v_{i}，故这种情况的最大价值为 f_{i-1,j-w_{i}}+v_{i}。 由此可以得出状态转移方程：&lt;/p&gt;
&lt;p&gt;物品放入背包后，总重量增加 &lt;span&gt;&lt;span&gt;wiw_i&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，背包剩余容量减少，所以容量是 &lt;span&gt;&lt;span&gt;j−wij-w_i&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;−&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;Pasted image 20240314225745.png&quot; loading=&quot;lazy&quot; width=&quot;1363&quot; height=&quot;601&quot; src=&quot;/_astro/pasted-image-20240314225745.BcgMsJt7_5Arpw.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20240314225745.png&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;section&gt;&lt;h3&gt;1. 二维动态规划解法&lt;a href=&quot;#1-二维动态规划解法&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;最直接的思路是使用二维数组来记录状态。定义&lt;code&gt;dp[i][j]&lt;/code&gt;表示前&lt;code&gt;i&lt;/code&gt;个物品在背包容量为&lt;code&gt;j&lt;/code&gt;时所能达到的最大价值。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;状态转移方程&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;如果不选第&lt;code&gt;i&lt;/code&gt;个物品，&lt;code&gt;dp[i][j] = dp[i-1][j]&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;如果选第&lt;code&gt;i&lt;/code&gt;个物品，&lt;code&gt;dp[i][j] = dp[i-1][j-wi] + vi&lt;/code&gt;，其中&lt;code&gt;wi&lt;/code&gt;是第&lt;code&gt;i&lt;/code&gt;个物品的重量，&lt;code&gt;vi&lt;/code&gt;是其价值。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;综合以上两种情况：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dp[i][j]=max(dp[i−1][j],dp[i−1][j−wi]+vi)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：&lt;code&gt;O(n * W)&lt;/code&gt;，空间复杂度也是&lt;code&gt;O(n * W)&lt;/code&gt;。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;2. 一维动态规划优化&lt;a href=&quot;#2-一维动态规划优化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通过观察上述二维动态规划方程，可以发现&lt;code&gt;dp[i][j]&lt;/code&gt;只依赖于&lt;code&gt;dp[i-1][j]&lt;/code&gt;和&lt;code&gt;dp[i-1][j-wi]&lt;/code&gt;。因此，&lt;code&gt;dp&lt;/code&gt;数组当前行的值只与前一行有关，所以我们可以通过一维数组来保存这些状态，从而降低空间复杂度。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;优化思路&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;使用一维数组&lt;code&gt;dp[j]&lt;/code&gt;，表示在背包容量为&lt;code&gt;j&lt;/code&gt;时，能得到的最大价值。&lt;/li&gt;
&lt;li&gt;按照从大到小的顺序更新&lt;code&gt;dp[j]&lt;/code&gt;，这样可以确保在计算&lt;code&gt;dp[j]&lt;/code&gt;时，&lt;code&gt;dp[j-wi]&lt;/code&gt;使用的是上一轮的值，即“前一行”的状态。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;状态转移方程&lt;/strong&gt;（与二维数组时类似）&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dp[j]=max(dp[j],dp[j−wi]+vi)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;</content:encoded></item><item><title>最大上升三元组数量</title><link>https://blog.81vm3.xyz/posts/max-increasing-triples/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/max-increasing-triples/</guid><description>用两棵树状数组统计数组中最大上升三元组数量的 C++ 实现。</description><pubDate>Sun, 01 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;数组离散化
树状数组
前缀和&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;思路&lt;a href=&quot;#思路&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;要求统计满足 &lt;span&gt;&lt;span&gt;i&amp;lt;j&amp;lt;ki &amp;lt; j &amp;lt; k&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 且 &lt;span&gt;&lt;span&gt;ai&amp;lt;aj&amp;lt;aka_i &amp;lt; a_j &amp;lt; a_k&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 的上升三元组数量。把每个位置 &lt;span&gt;&lt;span&gt;jj&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 当作三元组的中间元素，问题拆成两步：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;第一层（树状数组 f1）&lt;/strong&gt;：从左往右扫描，&lt;code&gt;f1.add(idx, 1)&lt;/code&gt; 记录值 &lt;code&gt;idx&lt;/code&gt; 出现次数。对当前值 &lt;code&gt;idx&lt;/code&gt;，&lt;code&gt;f1.query(idx - 1)&lt;/code&gt; 就是它左边比它小的数的个数，记作 &lt;span&gt;&lt;span&gt;smalljsmall_j&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第二层（树状数组 f2）&lt;/strong&gt;：&lt;code&gt;f2.add(idx, small_j)&lt;/code&gt;，即在位置 &lt;code&gt;idx&lt;/code&gt; 上累加「以某个值结尾、且比它小的左边元素数」。这样 &lt;code&gt;f2.query(idx - 1)&lt;/code&gt; 累计的就是所有「两两上升对」中，右端值比 &lt;code&gt;idx&lt;/code&gt; 小的对数。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;扫到 &lt;code&gt;i&lt;/code&gt; 时执行 &lt;code&gt;ans += f2.query(idx - 1)&lt;/code&gt;，即以 &lt;span&gt;&lt;span&gt;aia_i&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 作为第三个元素，能接上的上升对数量。三层递推：单个数 → 上升对 → 上升三元组。&lt;/p&gt;&lt;p&gt;值域可能很大（long long），所以先对数组&lt;strong&gt;离散化&lt;/strong&gt;（排序副本 + &lt;code&gt;lower_bound&lt;/code&gt; 映射），再把离散化后的排名当作树状数组下标。&lt;/p&gt;&lt;p&gt;复杂度 &lt;span&gt;&lt;span&gt;O(nlog⁡n)O(n \log n)&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;O&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;lo&lt;span&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，空间 &lt;span&gt;&lt;span&gt;O(n)O(n)&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;O&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;bits/stdc++.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MAXN&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;typedef&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyTree&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sz&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;MyTree&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sz&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;sz&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sz&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sz&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lowbit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sz&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lowbit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;sum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lowbit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sum&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;MyTree&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f1&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;MAXN&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;f2&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;MAXN&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;solve&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;span&gt;  // 复制数组用于排序&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;)), &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;span&gt; // 仅排序副本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lower_bound&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;)), &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;idx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;f1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;idx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;f2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;idx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;idx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;span&gt;  // 确保索引合法&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;idx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ans&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;endl&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;66&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;67&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ios_base::&lt;/span&gt;&lt;span&gt;sync_with_stdio&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;68&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tie&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;69&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tie&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;70&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;71&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;solve&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;72&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;73&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;</content:encoded></item><item><title>带权路径长度（WPL）</title><link>https://blog.81vm3.xyz/posts/weighted-path-length/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/weighted-path-length/</guid><description>带权路径长度 WPL 的定义、计算公式与哈夫曼树示例。</description><pubDate>Sun, 10 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在讨论树结构，特别是在哈夫曼树等数据压缩和编码算法中，一个关键的概念是“带权路径长度”（Weighted Path Length，WPL）。这个概念对于理解树的效率和优化有重要作用。&lt;/p&gt;
&lt;section&gt;&lt;h3&gt;带权路径长度（WPL）&lt;a href=&quot;#带权路径长度wpl&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;带权路径长度是树中 &lt;strong&gt;所有叶节点&lt;/strong&gt; 的路径长度与其权值的乘积之和。具体来说：&lt;/p&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;/li&gt;
&lt;/ul&gt;&lt;p&gt;对于哈夫曼树，WPL 最小化是其设计的关键目的，意味着常见的数据（高权值）具有较短的路径长度，从而实现整体存储和传输的效率。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;WPL 的计算&lt;a href=&quot;#wpl-的计算&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;假设一个树结构中，每个叶节点 &lt;span&gt;&lt;span&gt;nin_i&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 有一个权值 &lt;span&gt;&lt;span&gt;wiw_i&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 和一个从根到该节点的路径长度 &lt;span&gt;&lt;span&gt;lil_i&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，WPL 计算公式为：&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;WPL=∑i=1kwi×li\text{WPL} = \sum_{i=1}^{k} w_i \times l_i&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;WPL&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;∑&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;其中 &lt;span&gt;&lt;span&gt;kk&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 是叶节点的数量。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;示例&lt;a href=&quot;#示例&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;考虑一个简单的哈夫曼树：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/ \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;5   *&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/ \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2   3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，数字代表权值，星号 (*) 表示内部节点（其权值是子节点权值的和）：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;权值为 5 的节点路径长度为 1。&lt;/li&gt;
&lt;li&gt;权值为 2 的节点路径长度为 2。&lt;/li&gt;
&lt;li&gt;权值为 3 的节点路径长度为 2。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;计算 WPL:&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;WPL=(5×1)+(2×2)+(3×2)=5+4+6=15WPL = (5 \times 1) + (2 \times 2) + (3 \times 2) = 5 + 4 + 6 = 15&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;W&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>MEX：最小非负整数</title><link>https://blog.81vm3.xyz/posts/mex/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/mex/</guid><description>MEX 的三个性质，以及用 set + 计数数组支持插入删除后 O(log n) 查询 MEX 的实现。</description><pubDate>Sun, 20 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;MEX 即一个数组中的最小非负整数，它满足下面三个性质：&lt;/p&gt;
&lt;p&gt;只有在添加的数等于当前序列的mex时，mex的值才会变化。
添加操作只会使得mex变大
删除操作会使得mex的值变小。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://codeforces.com/contest/1629/problem/C&quot; target=&quot;_blank&quot;&gt;Problem - C - Codeforces&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;对于一个随时插入，删除元素的数组，想高效的查询mex可使用 set 和 一个计数数组&lt;/p&gt;
&lt;p&gt;用一个set&amp;lt;int&amp;gt; st 来记录没有出现过的数，然后直接取最小值就可以了，当然需要一个cnt来计数。&lt;/p&gt;
&lt;p&gt;最小值用begin取得&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Mex&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Mex&lt;/span&gt;&lt;span&gt;() { &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;erase&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;del&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;() { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(); }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded></item><item><title>C++ priority_queue 优先队列</title><link>https://blog.81vm3.xyz/posts/cpp-priority-queue/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/cpp-priority-queue/</guid><description>C++ priority_queue 的基本用法与通过自定义比较实现最小堆。</description><pubDate>Sun, 06 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;C++中的优先队列（priority queue）是一种用于维护一组元素构成的集合的容器适配器，其中每个元素都有一个优先级。添加到优先队列中的元素将按照其优先级排序，优先级最高的元素将首先被移除。优先队列通常使用堆（heap）数据结构来实现，以支持高效的元素插入和移除操作。&lt;/p&gt;
&lt;p&gt;在C++标准库中，优先队列通过&lt;code&gt;priority_queue&lt;/code&gt;模板类提供，该模板类定义在头文件&lt;code&gt;&amp;lt;queue&amp;gt;&lt;/code&gt;中。&lt;/p&gt;
&lt;section&gt;&lt;h3&gt;基本用法&lt;a href=&quot;#基本用法&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;以下是&lt;code&gt;priority_queue&lt;/code&gt;的基本用法示例：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;queue&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 创建一个int类型的优先队列，默认使用std::less&amp;lt;int&amp;gt;，&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 即最大值优先&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;priority_queue&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 向优先队列中插入元素&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 遍历优先队列（这不是最好的方法，因为会改变队列内容）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;empty&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 访问队头元素&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;top&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot; &quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 移除队头元素&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;pop&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; std::&lt;/span&gt;&lt;span&gt;endl&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;输出结果将是：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;30 20 10 5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;自定义优先级&lt;a href=&quot;#自定义优先级&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;你可以通过定义自己的比较函数或者重载&lt;code&gt;operator&amp;lt;&lt;/code&gt;来实现自定义类型的优先级排序。比如，使用结构体并自定义优先级规则：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;queue&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyStruct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 自定义比较函数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator&lt;/span&gt;&lt;span&gt;&amp;lt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyStruct&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 这里定义的是最小值优先&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;other&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;priority_queue&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyStruct&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 向优先队列中插入元素&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 遍历优先队列&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;empty&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;top&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot; &quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pq&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;pop&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;cout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; std::&lt;/span&gt;&lt;span&gt;endl&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;输出结果将是：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;5 10 20 30&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，自定义的比较运算符让我们能够实现最小值优先的排序逻辑。注意，当使用自定义类型时，必须确保提供用于比较元素的机制，要么通过重载&lt;code&gt;operator&amp;lt;&lt;/code&gt;，要么通过提供自定义的比较函数对象。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>字典树</title><link>https://blog.81vm3.xyz/posts/trie/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/trie/</guid><description>字典树的结构特点与插入/查找模板，以及用 01-trie 维护异或极值的方法与例题。</description><pubDate>Sun, 22 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;数据结构&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：字典树支持高效的前缀查找。其次，通过共享前缀来节省空间，多个以相同前缀开头的字符串只需存储一份前缀。再次，字典树的节点不直接存储完整的字符串，而是通过从根节点到该节点的路径构成字符串
最后，字典树支持插入、查找、删除和前缀匹配等多种操作
&lt;strong&gt;插入和查找操作的时间复杂度均为 O(m)，其中 m 是字符串的长度&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结构定义&lt;/strong&gt;：字典树通常由两个主要结构组成。首先是TrieNode（节点），每个节点包含一个子节点的映射（通常使用哈希表或数组）和一个布尔值 end，指示该节点是否为某个字符串的结尾。其次是Trie（字典树），它包含一个指向根节点的指针，所有字符串的插入和查找操作都从根节点开始&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;trie&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nex&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;100000&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exist&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;100000&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;span&gt;  // 该结点结尾的字符串是否存在&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span&gt;  // 插入字符串&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;a&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;nex&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;nex&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;cnt&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt;  // 如果没有，就添加结点&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nex&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;exist&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;char&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span&gt;  // 查找字符串&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;a&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;nex&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nex&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;][&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exist&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
&lt;section&gt;&lt;h3&gt;维护异或极值&lt;a href=&quot;#维护异或极值&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;XOR 异或
将数的二进制表示看做一个字符串，就可以建出字符集为 &lt;span&gt;&lt;span&gt;{0,1}\{0,1\}&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 的 trie 树。&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://codeforces.com/problemset/problem/706/D&quot; target=&quot;_blank&quot;&gt;Problem - 706D - Codeforces&lt;/a&gt;&lt;/p&gt;&lt;p&gt;我们考虑在一个&lt;strong&gt;01字典树&lt;/strong&gt;（每个节点是0或1）里插入所有数的二进制表示。比如要插入一个32位整数，就从高位到低位一位一位插。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;插入过程：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;从最高位（比如31位）往最低位0位走。&lt;/li&gt;
&lt;li&gt;每一位如果是0，就走/建0儿子，否则走/建1儿子。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;查询最大异或值的过程：&lt;/strong&gt;
假设现在要查一个数x，想找集合中一个数，使得异或值最大。异或要大，意味着尽量在每一位上异或出1。怎么做？&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;从高位到低位一位一位走。&lt;/li&gt;
&lt;li&gt;每一位，&lt;strong&gt;优先找跟x当前位不同的方向&lt;/strong&gt;（因为1异或0 = 1，能让结果高位出现1）。&lt;/li&gt;
&lt;li&gt;如果能走，就走异位；不能走，就只能走同位。&lt;/li&gt;
&lt;li&gt;边走边计算异或值。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;查询最小异或值的过程（比如如果需要）&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;每一位，&lt;strong&gt;优先走跟x当前位相同的方向&lt;/strong&gt;（因为0异或0=0，1异或1=0，结果小）。&lt;/li&gt;
&lt;li&gt;走不了再走异位。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded></item><item><title>XOR 异或的性质与可差分性</title><link>https://blog.81vm3.xyz/posts/xor/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/xor/</guid><description>XOR 的交换律、结合律与可差分性：用前缀异和处理区间异或和的两道例题。</description><pubDate>Sun, 08 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;位运算&lt;/p&gt;
&lt;p&gt;XOR 满足&lt;strong&gt;交换律和结合律&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;结论1: 如果奇数位和偶数位的 XOR 结果相等，则整个数组的 XOR 结果为 0&lt;/li&gt;
&lt;li&gt;结论2:  a xor b = 0 当且仅当 a == b&lt;/li&gt;
&lt;li&gt;结论3:  a xor 0 = 0&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://codeforces.com/problemset/problem/1872/E&quot; target=&quot;_blank&quot;&gt;Problem - 1872E - Codeforces&lt;/a&gt;
巧妙异或前缀和&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://codeforces.com/problemset/problem/1516/B&quot; target=&quot;_blank&quot;&gt;Problem - 1516B - Codeforces&lt;/a&gt;
此题中由于异或运算满足交换律，所以相邻谁先异或谁是没有关系的，
然后就可以把问题转化成求分界点，两边的异或和相等 (或者三块相等)。
然后就暴力枚举两个分界点L，R&lt;/p&gt;
&lt;p&gt;枚举 “隔板点”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一个数组中的异或和是可差分的信息&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;solve&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;YES&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;j&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;YES&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;NO&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded></item><item><title>并查集</title><link>https://blog.81vm3.xyz/posts/dsu/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/dsu/</guid><description>并查集的基本概念（Union/Find）与路径压缩 C++ 模板。</description><pubDate>Sun, 25 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;并查集是一种用于管理元素所属集合的数据结构，实现为一个森林，其中&lt;strong&gt;每棵树表示一个集合&lt;/strong&gt;，树中的节点表示对应集合中的元素。&lt;/p&gt;
&lt;p&gt;顾名思义，并查集支持两种操作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;合并（Union）：合并两个元素所属集合（合并对应的树）&lt;/li&gt;
&lt;li&gt;查询（Find）：查询某个元素所属集合（查询对应的树的根节点），这可以用于判断两个元素是否属于同一集合&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;并查集在经过修改后可以支持单个元素的删除、移动；使用动态开点线段树还可以实现可持久化并查集。
&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;Pasted image 20240310165444.png&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;521&quot; src=&quot;/_astro/pasted-image-20240310165444.BuMka81X_Z7yXpB.webp&quot; /&gt;&lt;figcaption&gt;Pasted image 20240310165444.png&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dsu&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;explicit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dsu&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) : &lt;/span&gt;&lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;std::&lt;/span&gt;&lt;span&gt;iota&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;]));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unite&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pa&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded></item><item><title>数组离散化</title><link>https://blog.81vm3.xyz/posts/array-discretization/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/array-discretization/</guid><description>数组离散化的三种 C++ 写法：sort+unique、lower_bound 映射与宏封装。</description><pubDate>Mon, 12 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;当你需要比较元素的大小，或者节省空间的情况:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 离散化&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;erase&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;unique&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;)), &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 映射离散化索引（1-based index）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;index_map&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;v_sorted&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;cin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arr&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;span&gt;  // 复制数组用于排序&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;)), &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;span&gt; // 仅排序副本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lower_bound&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;next&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;)), &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sorted_arr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;all&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unq_all&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;erase&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;unique&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)), &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sort_all&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sort_all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;unq_all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get_id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;ll&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lower_bound&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;begin&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; // 下标从1开始&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded></item><item><title>Vue 组件属性 Props</title><link>https://blog.81vm3.xyz/posts/vue-component-props/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/vue-component-props/</guid><description>Props 父子传值的基础用法、类型校验、默认值与必填约束。</description><pubDate>Mon, 15 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在 Vue 组件中，属性（Props）用于在父组件和子组件之间传递数据。以下是 Vue 组件属性的关键概念：&lt;/p&gt;
&lt;section&gt;&lt;h3&gt;1. &lt;strong&gt;基础使用&lt;/strong&gt;&lt;a href=&quot;#1-基础使用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;子组件模板（单文件组件的 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 块）：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;Message: {{ message }}&amp;lt;/&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;对应的脚本（Options API）：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;message&quot;&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;// 简单定义 props&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;父组件使用：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ChildComponent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Hello Vue!&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;2. &lt;strong&gt;类型验证&lt;/strong&gt;&lt;a href=&quot;#2-类型验证&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Vue 允许为 props 指定数据类型：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;props: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;message: String,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;count: Number,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;isActive: Boolean,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;items: Array,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;user: Object,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;callback: Function&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;3. &lt;strong&gt;默认值&lt;/strong&gt;&lt;a href=&quot;#3-默认值&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;如果父组件未传递 prop，可以提供默认值：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;props: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;count: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type: Number,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;default: 0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;4. &lt;strong&gt;必填&lt;/strong&gt;&lt;a href=&quot;#4-必填&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;如果某个 prop 必须提供：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;props: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type: String,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;required: true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;5. &lt;strong&gt;自定义验证&lt;/strong&gt;&lt;a href=&quot;#5-自定义验证&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;props: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rating: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type: Number,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;validator: value =&amp;gt; value &amp;gt;= 0 &amp;amp;&amp;amp; value &amp;lt;= &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;6. &lt;strong&gt;动态绑定&lt;/strong&gt;&lt;a href=&quot;#6-动态绑定&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ChildComponent&lt;/span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;parentMessage&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;:message&lt;/code&gt; 表示 message 由父组件的数据 &lt;code&gt;parentMessage&lt;/code&gt; 绑定，而不是字符串。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;7. &lt;strong&gt;非 Prop Attribute&lt;/strong&gt;&lt;a href=&quot;#7-非-prop-attribute&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;如果子组件没有声明某个 prop，Vue 会把它当作普通 HTML 特性传递：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ChildComponent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;custom-style&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;如果 &lt;code&gt;ChildComponent&lt;/code&gt; 没有 &lt;code&gt;props: [&quot;class&quot;]&lt;/code&gt;，这个 &lt;code&gt;class&lt;/code&gt; 会应用到子组件的根元素。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;8. &lt;strong&gt;单向数据流&lt;/strong&gt;&lt;a href=&quot;#8-单向数据流&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Prop 只能在子组件内部 &lt;strong&gt;读取&lt;/strong&gt;，不能修改。如果要修改，推荐使用：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;局部数据拷贝&lt;/strong&gt;：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;props: [&quot;count&quot;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;data() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;return { localCount: this.count };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;$emit 事件通知父组件&lt;/strong&gt;：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;click&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$emit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;update-count&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;Increase&amp;lt;/&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;9. &lt;strong&gt;使用 &lt;code&gt;defineProps&lt;/code&gt;（Vue 3 Composition API）&lt;/strong&gt;&lt;a href=&quot;#9-使用-definepropsvue-3-composition-api&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;单文件组件 &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt; 块中：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;defineProps&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Number&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Vue 组件的属性机制可以帮助父子组件高效通信，同时保持组件的封装性和可复用性。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Vue 生命周期钩子</title><link>https://blog.81vm3.xyz/posts/vue-lifecycle/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/vue-lifecycle/</guid><description>Vue 组件创建、挂载、更新各阶段的生命周期钩子与可操作范围对照。</description><pubDate>Tue, 02 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h3&gt;&lt;strong&gt;（1）创建阶段&lt;/strong&gt;&lt;a href=&quot;#1创建阶段&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;组件实例被初始化，但 &lt;strong&gt;DOM 还未渲染&lt;/strong&gt;，可以在这阶段进行数据初始化、调用 API 获取数据等操作。&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;钩子&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;beforeCreate()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;数据和事件都未初始化&lt;/strong&gt;，只能访问 &lt;code&gt;methods&lt;/code&gt; 但无法访问 &lt;code&gt;data&lt;/code&gt;、&lt;code&gt;computed&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;created()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;实例创建完成，data 已初始化&lt;/strong&gt;，可以进行 &lt;strong&gt;异步请求&lt;/strong&gt;，但 &lt;strong&gt;DOM 还未渲染&lt;/strong&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;&lt;strong&gt;（2）挂载阶段&lt;/strong&gt;&lt;a href=&quot;#2挂载阶段&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;组件被挂载到 &lt;strong&gt;DOM&lt;/strong&gt;，此时可以进行 &lt;strong&gt;DOM 操作&lt;/strong&gt; 或者 &lt;strong&gt;获取 DOM 元素&lt;/strong&gt;。&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;钩子&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;beforeMount()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;模板已编译，&lt;strong&gt;但虚拟 DOM 还未挂载到真实 DOM&lt;/strong&gt;，可以操作 &lt;code&gt;data&lt;/code&gt;，但不能操作 &lt;code&gt;DOM&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;mounted()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;组件 &lt;strong&gt;已挂载到真实 DOM&lt;/strong&gt;，&lt;strong&gt;可操作 DOM、进行 AJAX 请求&lt;/strong&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;hr /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h3&gt;&lt;strong&gt;（3）更新阶段&lt;/strong&gt;&lt;a href=&quot;#3更新阶段&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当 &lt;code&gt;data&lt;/code&gt; 发生变化时，Vue 组件会重新渲染。&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;钩子&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;beforeUpdate()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;组件 &lt;strong&gt;更新前&lt;/strong&gt; 触发，数据已经改变 &lt;strong&gt;但 DOM 还未更新&lt;/strong&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;updated()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;组件 &lt;strong&gt;更新后&lt;/strong&gt; 触发，&lt;strong&gt;DOM 已更新&lt;/strong&gt;，可以执行依赖更新 DOM 的操作。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;</content:encoded></item><item><title>Vue v-model 双向数据绑定</title><link>https://blog.81vm3.xyz/posts/vue-v-model/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/vue-v-model/</guid><description>v-model 指令在表单控件与组件间同步数据的作用、特点与 Vue 3 自定义绑定。</description><pubDate>Mon, 18 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h3&gt;&lt;strong&gt;&lt;code&gt;v-model&lt;/code&gt; 在 Vue 中的作用&lt;/strong&gt;&lt;a href=&quot;#v-model-在-vue-中的作用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;v-model&lt;/code&gt; 是 Vue 提供的&lt;strong&gt;双向数据绑定&lt;/strong&gt;指令，用于在表单控件（如 &lt;code&gt;input&lt;/code&gt;、&lt;code&gt;textarea&lt;/code&gt;、&lt;code&gt;select&lt;/code&gt;）和组件之间同步数据。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;绑定的数据会随着用户输入自动更新。&lt;/li&gt;
&lt;li&gt;适用于 &lt;code&gt;input&lt;/code&gt;、&lt;code&gt;textarea&lt;/code&gt;、&lt;code&gt;select&lt;/code&gt; 等表单控件。&lt;/li&gt;
&lt;li&gt;Vue 3 中可以自定义 &lt;code&gt;v-model&lt;/code&gt; 绑定的属性。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;本质是语法糖&lt;a href=&quot;#本质是语法糖&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在原生表单元素上，&lt;code&gt;v-model&lt;/code&gt; 约等于「value 绑定 + input 事件回写」：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- 等价于 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@input&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text = $event.target.value&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;修饰符&lt;a href=&quot;#修饰符&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- lazy：改为 change 事件触发（失焦才同步） --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model.lazy&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- trim：自动去掉首尾空格 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model.trim&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- number：把输入转为数字 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model.number&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;age&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;number&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;在组件上使用（Vue 3）&lt;a href=&quot;#在组件上使用vue-3&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;组件上的 &lt;code&gt;v-model&lt;/code&gt; 默认展开为 &lt;code&gt;modelValue&lt;/code&gt; prop 和 &lt;code&gt;update:modelValue&lt;/code&gt; 事件：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- 父组件 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyInput&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;keyword&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- 等价于 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyInput&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:model-value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;keyword&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@update:model-value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;keyword = $event&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 子组件 MyInput&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineProps&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;&quot;modelValue&quot;&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;emit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defineEmits&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;&quot;update:modelValue&quot;&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Vue 3 还支持多个双向绑定，通过参数区分：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;MyForm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model:title&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;bookTitle&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-model:author&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;bookAuthor&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;自定义组件也可以声明 &lt;code&gt;v-model&lt;/code&gt; 的 arg、事件名与修饰符（&lt;code&gt;defineModel()&lt;/code&gt; 更简洁）。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Vue v-bind 动态属性绑定</title><link>https://blog.81vm3.xyz/posts/vue-v-bind/</link><guid isPermaLink="true">https://blog.81vm3.xyz/posts/vue-v-bind/</guid><description>v-bind 将 JavaScript 表达式绑定到 HTML attribute 的用法。</description><pubDate>Tue, 05 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;code&gt;v-bind&lt;/code&gt; 是 Vue.js 中用于动态绑定 HTML attribute（属性）的指令。它允许你在模板中将 JavaScript 表达式的值绑定到 HTML 元素的属性上，使页面能够根据数据的变化自动更新。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;基本语法&lt;a href=&quot;#基本语法&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- 完整写法 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-bind:href&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;url&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;链接&amp;lt;/&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- 缩写：冒号 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:href&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;url&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;链接&amp;lt;/&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;绑定的值可以是任意 JavaScript 表达式：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;img&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:src&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;baseUrl + &apos;/logo.png&apos;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:alt&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;title&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:width&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;size * 2&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;绑定 class 与 style&lt;a href=&quot;#绑定-class-与-style&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这是 &lt;code&gt;v-bind&lt;/code&gt; 最常用的场景之一，支持对象语法和数组语法：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- 对象语法：条件为真时应用该 class --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;{ active: isActive, &apos;text-red&apos;: hasError }&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- 数组语法 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;[baseClass, isActive ? &apos;active&apos; : &apos;&apos;]&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;!-- style 对象语法 --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;{ color: textColor, fontSize: fontSize + &apos;px&apos; }&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;动态 attribute 名&lt;a href=&quot;#动态-attribute-名&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Vue 3 支持用方括号把 attribute 名也变成表达式：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:[attributeName]&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;url&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;这里的 attributeName 可以是动态的&amp;lt;/&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;与组件 props 的关系&lt;a href=&quot;#与组件-props-的关系&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在组件上使用 &lt;code&gt;:prop-name=&quot;value&quot;&lt;/code&gt; 时，&lt;code&gt;v-bind&lt;/code&gt; 就是把父组件的数据传给子组件的 prop。配合 &lt;code&gt;v-bind=&quot;obj&quot;&lt;/code&gt; 还可以一次性把整个对象展开为多个 props：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;UserCard&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v-bind&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;userFields&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;一句话总结：插值表达式负责把值写进文本，&lt;code&gt;v-bind&lt;/code&gt; 负责把值写进 attribute。&lt;/p&gt;&lt;/section&gt;</content:encoded></item></channel></rss>