<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on 鹿鸣青野的blog</title><link>https://www.sylgalaxy.xyz/posts/</link><description>Recent content in Posts on 鹿鸣青野的blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Tue, 13 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.sylgalaxy.xyz/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>AI 时代 Qt 开发新路线(ACP + 专家模式)</title><link>https://www.sylgalaxy.xyz/posts/ai-qt-new-era/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/ai-qt-new-era/</guid><description>&lt;blockquote&gt;
&lt;p&gt;适用人群:有 Qt/C++ 基础,想了解 2026 年 AI 如何重塑 Qt 开发工作流的人。
更新日期:2026-08-21&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#1-%E6%97%B6%E4%BB%A3%E8%83%8C%E6%99%AFide-%E6%8E%A5%E5%85%A5-acp"&gt;1. 时代背景:IDE 接入 ACP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#2-qt%E4%B8%93%E5%AE%B6%E6%A8%A1%E5%BC%8F%E9%99%8D%E4%BD%8E-llm-%E5%B9%BB%E8%A7%89%E7%9A%84%E6%A0%B8%E5%BF%83%E6%89%8B%E6%AE%B5"&gt;2. qt专家模式:降低 LLM 幻觉的核心手段&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#3-%E6%9C%AC%E5%8C%BA%E8%90%BD%E5%9C%B0%E9%A1%B9%E7%9B%AE"&gt;3. 本区落地项目&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#4-%E5%85%B3%E9%94%AE%E6%8A%80%E6%9C%AF%E7%82%B9"&gt;4. 关键技术点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#5-%E5%AD%A6%E4%B9%A0%E6%96%B9%E5%90%91"&gt;5. 学习方向&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="1-时代背景ide-接入-acp"&gt;1. 时代背景:IDE 接入 ACP&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;:AI 不再是一个网页对话框,而是被「缝」进开发工具——Qt Creator 20 原生支持四种 AI 连接方式,其中 ACP Client 让 AI 代理能直接改代码、跑命令、触发构建。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ACP(Agent Client Protocol)&lt;/strong&gt; 是客户端软件与 AI 编程代理之间的&lt;strong&gt;开放协议&lt;/strong&gt;(Zed 团队维护),让 IDE 原生出现「侧栏 agent」——类似 VS Code Copilot 侧栏的效果。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;已确认(2026-08-21,官方文档)&lt;/strong&gt;:Qt Creator 20 的「Using AI」一节列出四种 AI 扩展:&lt;/li&gt;
&lt;/ul&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;strong&gt;ACP Client&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;用 ACP 连接理解你代码库的 AI 代理,替你改文件、跑命令、触发构建(需配合 MCP Server 扩展启用动作)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;接入 Copilot,编辑模式内补全建议&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;让 AI 助手经 MCP 控制 Qt Creator(调试 / 构建 / 工程管理)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Qt AI Assistant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Qt 自带编程助手,接 LLM 后自动补全、建议修复、写测试与文档&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;官方链接:https://doc.qt.io/qtcreator/creator-using-ai.html(20.0 快照:https://doc-snapshots.qt.io/qtcreator-20.0/creator-using-ai.html)&lt;/li&gt;
&lt;li&gt;意义:AI 从「聊天窗口」升级为「&lt;strong&gt;开发环境里的协作者&lt;/strong&gt;」;而要让这个协作者说对 Qt,就得解决它记不住 / 会乱编 API 的问题 —— 这就是下一节。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-qt专家模式降低-llm-幻觉的核心手段"&gt;2. qt专家模式:降低 LLM 幻觉的核心手段&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;:不让 AI 背文档,而是让它「先抓官方文档回来,再基于抓到的文本作答」——这就是 Agentic RAG。&lt;/p&gt;</description></item><item><title>atomic 原子操作</title><link>https://www.sylgalaxy.xyz/posts/go-03-05-atomic/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-05-atomic/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 的 std::atomic&lt;T&gt; 在 Go 里是 sync/atomic 包：无锁计数器、无锁标志位、无锁状态机的最优解&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sync/atomic&lt;/code&gt; 提供对内存地址的&lt;strong&gt;原子操作&lt;/strong&gt;：&lt;code&gt;Add&lt;/code&gt;（原子加）、&lt;code&gt;Load&lt;/code&gt;（原子读）、&lt;code&gt;Store&lt;/code&gt;（原子写）、&lt;code&gt;CompareAndSwap&lt;/code&gt;（比较并交换）、&lt;code&gt;Swap&lt;/code&gt;（交换）。它们作用于 &lt;code&gt;int32&lt;/code&gt; / &lt;code&gt;int64&lt;/code&gt; / &lt;code&gt;uint32&lt;/code&gt; / &lt;code&gt;uint64&lt;/code&gt; / &lt;code&gt;uintptr&lt;/code&gt; / &lt;code&gt;unsafe.Pointer&lt;/code&gt; 以及 &lt;code&gt;atomic.Value&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;和 Mutex 相比，原子操作是&lt;strong&gt;免锁（lock-free）&lt;strong&gt;的：既不阻塞、也无上下文切换开销，在「高频计数器、状态标志、一次性初始化标志」这类场景下性能明显优于锁。代价是&lt;/strong&gt;只能保护单变量&lt;/strong&gt;，且不能声明「一段代码的整齐」。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：读——&lt;code&gt;Load&lt;/code&gt;、写——&lt;code&gt;Store&lt;/code&gt;、改——&lt;code&gt;Add&lt;/code&gt; / &lt;code&gt;CompareAndSwap&lt;/code&gt;。把「多步的读-改-写」用一个 CAS 原子完成，是理解 Go 原子操作的钥匙。C++ 里的 &lt;code&gt;std::atomic&amp;lt;int&amp;gt;&lt;/code&gt; 心智模型几乎原样平移，差异只在 API 命名和哪些类型支持。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::atomic&amp;lt;int&amp;gt; n{0}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var n atomic.Int64&lt;/code&gt;（或 &lt;code&gt;var n int64&lt;/code&gt; + &lt;code&gt;atomic.AddInt64&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;Go 1.19+ 有类型化 &lt;code&gt;atomic.Int64&lt;/code&gt;，更顺手&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原子加&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n.fetch_add(1)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.AddInt64(&amp;amp;n, 1)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 返回新值；&lt;code&gt;AddInt32&lt;/code&gt; / &lt;code&gt;AddUint64&lt;/code&gt; 等按类型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原子读&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n.load()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.LoadInt64(&amp;amp;n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 读不写也有可能被优化异常，必须用 Load&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原子写&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n.store(42)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.StoreInt64(&amp;amp;n, 42)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 生硬但显式；&lt;code&gt;Load&lt;/code&gt;/&lt;code&gt;Store&lt;/code&gt; 配对使用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;比较并交换&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n.compare_exchange_strong(expected, desired)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.CompareAndSwapInt64(&amp;amp;n, old, new)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CAS 失败返回 false，循环重试是惯用法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原子交换&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n.exchange(42)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.SwapInt64(&amp;amp;n, 42)&lt;/code&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;code&gt;std::atomic&amp;lt;bool&amp;gt;&lt;/code&gt; / &lt;code&gt;std::atomic&amp;lt;T*&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.Bool&lt;/code&gt;（1.19+）/ &lt;code&gt;atomic.Pointer[T]&lt;/code&gt;（1.19+）&lt;/td&gt;
&lt;td&gt;Go 类型化版本避免手写 unsafe.Pointer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;任意值原子存取&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::mutex&lt;/code&gt; 包 struct&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.Value&lt;/code&gt;（存储任意类型）&lt;/td&gt;
&lt;td&gt;Value 的 Load 要求「上次存过的类型」&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;内存顺序&lt;/td&gt;
&lt;td&gt;&lt;code&gt;memory_order_relaxed&lt;/code&gt; / &lt;code&gt;seq_cst&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 不暴露 memory_order，原子操作只有一种语义&lt;/td&gt;
&lt;td&gt;自 Go 1.19 起内存模型正式规定：原子访问之间顺序一致（sequentially consistent）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-计数器addint64--adduint64"&gt;3.1 计数器：&lt;code&gt;AddInt64&lt;/code&gt; / &lt;code&gt;AddUint64&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;经典场景——无锁计数器，多 goroutine 并发累加。&lt;/p&gt;</description></item><item><title>Boost.Asio 回调机制初步窥探</title><link>https://www.sylgalaxy.xyz/posts/boost-note/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/boost-note/</guid><description>&lt;blockquote&gt;
&lt;p&gt;验证 Boost.Asio 开发环境 + 理解异步回调与 Qt 信号槽的对应关系&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="一环境验证异步定时器"&gt;一、环境验证：异步定时器&lt;/h2&gt;
&lt;p&gt;Asio 是纯头文件库（Header-Only），不需要 &lt;code&gt;b2.exe&lt;/code&gt; 编译，配置包含目录后即可 &lt;code&gt;#include&lt;/code&gt; 使用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;验证代码&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;boost/asio.hpp&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; boost&lt;span style="color:#f92672"&gt;::&lt;/span&gt;asio&lt;span style="color:#f92672"&gt;::&lt;/span&gt;io_context io;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; boost&lt;span style="color:#f92672"&gt;::&lt;/span&gt;asio&lt;span style="color:#f92672"&gt;::&lt;/span&gt;steady_timer timer(io, std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;chrono&lt;span style="color:#f92672"&gt;::&lt;/span&gt;seconds(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timer.async_wait([](&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; boost&lt;span style="color:#f92672"&gt;::&lt;/span&gt;system&lt;span style="color:#f92672"&gt;::&lt;/span&gt;error_code&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; ec) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;ec) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;gt;&amp;gt;&amp;gt; 3s elapsed, async callback fired&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;--- main thread continues immediately ---&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; io.run();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;预期输出&lt;/strong&gt;（顺序证明异步非阻塞）：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;--- main thread continues immediately ---
（3 秒间隔）
&amp;gt;&amp;gt;&amp;gt; 3s elapsed, async callback fired
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;证明了三件事&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>C/C++ 内存布局、程序构建与静态库动态库</title><link>https://www.sylgalaxy.xyz/posts/cpp-memory-layout/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-memory-layout/</guid><description>&lt;p&gt;从内存区域划分（&lt;code&gt;.text&lt;/code&gt; / &lt;code&gt;.rodata&lt;/code&gt; / &lt;code&gt;.data&lt;/code&gt; / &lt;code&gt;.bss&lt;/code&gt; / 栈 / 堆）讲到构建四阶段（预处理 → 编译 → 汇编 → 链接），再到静态库与动态库的创建、链接行为差异，末尾汇总易错点。&lt;/p&gt;
&lt;h2 id="一内存布局在构建阶段就确定"&gt;一、内存布局在构建阶段就确定&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Determined at Build Time：&lt;code&gt;.text&lt;/code&gt; / &lt;code&gt;.rodata&lt;/code&gt; / &lt;code&gt;.data&lt;/code&gt; / &lt;code&gt;.bss&lt;/code&gt; 的内存布局、大小在编译链接构建阶段就确定，不是程序跑起来才决定。这几段都属于 &lt;strong&gt;static lifetime 静态生命周期&lt;/strong&gt;，由编译器自动管理分配与释放，程序员不能手动干预申请释放。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;按数据类型、生命周期和作用域，C/C++ 程序的内存通常划分为五大区域：&lt;strong&gt;代码区、全局/静态存储区、栈区、堆区、常量区&lt;/strong&gt;。其中代码区对应 &lt;code&gt;.text&lt;/code&gt;，常量区对应 &lt;code&gt;.rodata&lt;/code&gt;，全局/静态存储区对应 &lt;code&gt;.data&lt;/code&gt; 与 &lt;code&gt;.bss&lt;/code&gt;，栈区与堆区则在运行时分配。&lt;/p&gt;
&lt;h3 id="1-text-代码段文本段--代码区"&gt;1. &lt;code&gt;.text&lt;/code&gt; 代码段（文本段 / 代码区）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;存储内容&lt;/strong&gt;：编译之后的机器指令（machine code），即写出的函数、&lt;code&gt;if&lt;/code&gt;/&lt;code&gt;for&lt;/code&gt; 循环、&lt;code&gt;main&lt;/code&gt; 函数等翻译成 CPU 能执行的指令。所有的函数定义、控制结构都会被转换成机器指令存放在这里。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大小&lt;/strong&gt;：Fixed size，构建阶段确定大小。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权限&lt;/strong&gt;：Read-only &lt;strong&gt;只读&lt;/strong&gt;，防止运行时篡改程序指令。这部分内存是共享的，在程序执行期间不会改变。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生命周期&lt;/strong&gt;：静态生命周期，进程整个运行期间都存在，进程退出由操作系统回收。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;管理&lt;/strong&gt;：完全由编译器、链接器自动管理，程序员没有 API 手动分配释放本段内存。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;编译时，&lt;code&gt;main&lt;/code&gt;、&lt;code&gt;func&lt;/code&gt; 等函数的代码被转换成机器指令存放在可执行文件的代码段中（此时还在磁盘上的可执行文件里）；程序运行时，操作系统把这些指令加载到内存的代码段，CPU 再从内存的代码段中读取并执行。&lt;/p&gt;
&lt;h3 id="2-rodata-只读数据段常量区"&gt;2. &lt;code&gt;.rodata&lt;/code&gt; 只读数据段（常量区）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;存储内容&lt;/strong&gt;：初始化后的常量，比如字符串字面量 &lt;code&gt;&amp;quot;hello world&amp;quot;&lt;/code&gt;、&lt;code&gt;const char *p = &amp;quot;abc&amp;quot;&lt;/code&gt; 这类常量字符串，以及全局 &lt;code&gt;const&lt;/code&gt; 常量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权限&lt;/strong&gt;：只读 Read-only，程序运行不能修改，写操作会触发段错误。这部分内存同样通常在程序执行期间不会改变。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;区分：&lt;code&gt;const int a = 10;&lt;/code&gt; 声明在全局放 rodata；局部 &lt;code&gt;const&lt;/code&gt; 变量本质还是在栈上。&lt;/p&gt;</description></item><item><title>C++ namespace、const 与 constexpr 知识点总结</title><link>https://www.sylgalaxy.xyz/posts/cpp-namespace-const-constexpr/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-namespace-const-constexpr/</guid><description>&lt;p&gt;命名空间、常量限定符与编译期常量三件套：语法、特点表、易混点（const 修饰指针的读法）、C++11/14/17/20 的演进，以及综合实战示例。&lt;/p&gt;
&lt;h2 id="1-namespace-命名空间"&gt;1. namespace 命名空间&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;namespace&lt;/code&gt;（命名空间）用于&lt;strong&gt;避免全局命名冲突&lt;/strong&gt;，把相关的类型、函数、变量组织在一起，形成逻辑上的&amp;quot;作用域边界&amp;quot;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：命名空间本质上是给标识符加了一个&amp;quot;姓氏&amp;quot;，从而把不同的名字区分开。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="11-基本声明与使用"&gt;1.1 基本声明与使用&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; Math {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;double&lt;/span&gt; PI &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.141592653589793&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; a &lt;span style="color:#f92672"&gt;+&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 使用 &amp;#34;::&amp;#34; 作用域限定符访问命名空间中的成员
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; Math&lt;span style="color:#f92672"&gt;::&lt;/span&gt;PI &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;endl; &lt;span style="color:#75715e"&gt;// 3.14159...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; Math&lt;span style="color:#f92672"&gt;::&lt;/span&gt;add(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;endl; &lt;span style="color:#75715e"&gt;// 7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-命名空间的特点"&gt;1.2 命名空间的特点&lt;/h3&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;/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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可匿名&lt;/td&gt;
&lt;td&gt;匿名命名空间相当于&amp;quot;文件内 static&amp;quot;，仅本文件可见&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可起别名&lt;/td&gt;
&lt;td&gt;&lt;code&gt;namespace M = Math;&lt;/code&gt; 简化访问&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="13-嵌套命名空间"&gt;1.3 嵌套命名空间&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; Outer {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; Inner {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;() { &lt;span style="color:#75715e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// C++17 起可以简写为：
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; Outer&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Inner {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bar&lt;/span&gt;() { &lt;span style="color:#75715e"&gt;/* ... */&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 访问方式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Outer&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Inner&lt;span style="color:#f92672"&gt;::&lt;/span&gt;foo();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Outer&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Inner&lt;span style="color:#f92672"&gt;::&lt;/span&gt;bar();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="14-匿名命名空间"&gt;1.4 匿名命名空间&lt;/h3&gt;
&lt;p&gt;匿名命名空间中的成员只在&lt;strong&gt;当前翻译单元&lt;/strong&gt;（.cpp 文件）内可见，等价于 &lt;code&gt;static&lt;/code&gt; 全局变量/函数，用于隔离实现细节。&lt;/p&gt;</description></item><item><title>C++ 并发编程：互斥锁、条件变量与原子操作</title><link>https://www.sylgalaxy.xyz/posts/cpp-concurrency-sync/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-concurrency-sync/</guid><description>&lt;p&gt;线程创建与 join/detach 之外的另一半问题：共享数据怎么同步。覆盖数据竞争、互斥锁的三种用法、条件变量生产者-消费者、原子操作与死锁。&lt;/p&gt;
&lt;h2 id="核心概念速查"&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;th&gt;关键点&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;同一时刻只允许一个线程进入&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::mutex&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;lock_guard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RAII 自动加解锁&lt;/td&gt;
&lt;td&gt;推荐,防遗漏&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;unique_lock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;更灵活的 RAII 锁&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;code&gt;std::condition_variable&lt;/code&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;code&gt;std::atomic&lt;/code&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;h2 id="为什么需要锁"&gt;为什么需要锁&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 无锁: 两个线程同时对 counter++ 可能丢失更新
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// counter++ 实际是&amp;#34;读-改-写&amp;#34;三步,可能交错
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; counter &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100000&lt;/span&gt;; &lt;span style="color:#f92672"&gt;++&lt;/span&gt;i)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;++&lt;/span&gt;counter; &lt;span style="color:#75715e"&gt;// 数据竞争!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="互斥锁三种用法"&gt;互斥锁三种用法&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;mutex&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;mutex g_mutex;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 方式1: 原始 lock/unlock(容易忘解锁,不推荐)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;f1&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; g_mutex.lock();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ... 临界区
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; g_mutex.unlock(); &lt;span style="color:#75715e"&gt;// 忘写或中间 return 就死锁
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 方式2: lock_guard (推荐,作用域结束自动解锁)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;f2&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;lock_guard&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;mutex&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; guard(g_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ... 临界区
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#75715e"&gt;// 这里自动 unlock
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 方式3: unique_lock (需要手动解锁/延迟加锁时)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;f3&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;unique_lock&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;mutex&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; lock(g_mutex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ... 临界区
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lock.unlock();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ... 不需要锁的部分
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="条件变量生产者-消费者"&gt;条件变量：生产者-消费者&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;mutex&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;condition_variable&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;queue&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;mutex mtx;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;condition_variable cv;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;queue&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; q;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 生产者
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;producer&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;; &lt;span style="color:#f92672"&gt;++&lt;/span&gt;i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;lock_guard&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;mutex&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; lock(mtx);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.push(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cv.notify_one(); &lt;span style="color:#75715e"&gt;// 通知一个等待的消费者
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 消费者
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;consumer&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (true) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;unique_lock&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;mutex&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; lock(mtx);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// wait 会: 释放锁等待 → 被唤醒 → 重新加锁
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cv.wait(lock, []{ &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;q.empty(); });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; val &lt;span style="color:#f92672"&gt;=&lt;/span&gt; q.front();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; q.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lock.unlock();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 处理 val...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="原子操作"&gt;原子操作&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;atomic&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;atomic&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; counter{&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// counter++ 是原子操作,无需加锁
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 适用场景: 计数器、标志位、自旋
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 对比:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 普通 int ++ → 需 mutex
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// atomic ++ → 无锁,更快
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="死锁"&gt;死锁&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;死锁四个必要条件:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. 互斥 资源只能一个线程占用
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. 持有并等待 拿着一个锁还想要另一个
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. 不可剥夺 别人不能抢走已持有的锁
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. 循环等待 两个线程彼此持有对方要的锁
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;例子:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;线程A持锁1等锁2 + 线程B持锁2等锁1 → 死锁
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;避免: 全局加锁顺序一致 / 用 std::lock 一次锁多个
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="常见坑"&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;th&gt;解决&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;code&gt;std::lock&lt;/code&gt; / RAII&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;code&gt;wait&lt;/code&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;一律 RAII 锁,变量尽量用 atomic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;忙等耗 CPU&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;h2 id="顿悟"&gt;顿悟&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;锁保护的是「数据」，不是「代码」&lt;/strong&gt;：所有访问同一个共享变量的地方都要用同一把锁，漏一处就出 bug。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAII 是防呆设计&lt;/strong&gt;：lock_guard 把&amp;quot;忘解锁&amp;quot;从可能性变成不可能，这是 C++ 现代写法核心。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原子 ≠ 万能&lt;/strong&gt;：只能处理单个变量的简单操作；涉及多个变量的一致性仍需锁。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;条件变量的 wait 里一定有循环&lt;/strong&gt;：防止假唤醒，这是教科书写法，别省。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="自测清单"&gt;自测清单&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;理解数据竞争为什么会丢更新&lt;/li&gt;
&lt;li&gt;会用 &lt;code&gt;std::mutex&lt;/code&gt; + &lt;code&gt;std::lock_guard&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;区分 lock_guard 与 unique_lock 的适用场景&lt;/li&gt;
&lt;li&gt;能写生产者-消费者（条件变量）&lt;/li&gt;
&lt;li&gt;理解死锁四条件，知道如何避免&lt;/li&gt;
&lt;li&gt;知道什么时候用 &lt;code&gt;std::atomic&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>C++ 函数指针、std::function 与 lambda</title><link>https://www.sylgalaxy.xyz/posts/cpp-function-pointer-lambda/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-function-pointer-lambda/</guid><description>&lt;p&gt;&amp;ldquo;把函数当值用&amp;quot;的三种写法：函数指针、&lt;code&gt;std::function&lt;/code&gt;、lambda。包含语法拆解、三者对比、捕获方式速记与常见坑。&lt;/p&gt;
&lt;h2 id="核心概念速查"&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;th&gt;关键点&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;存函数地址的变量&lt;/td&gt;
&lt;td&gt;C 风格,语法绕&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;std::function&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;通用函数包装器&lt;/td&gt;
&lt;td&gt;C++11,可存 lambda/仿函数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;lambda&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;匿名函数对象&lt;/td&gt;
&lt;td&gt;C++11,现代首选&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;lambda 使用外部变量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[ ]&lt;/code&gt; &lt;code&gt;[&amp;amp;]&lt;/code&gt; &lt;code&gt;[=]&lt;/code&gt; &lt;code&gt;[x]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="为什么需要函数指针"&gt;为什么需要函数指针&lt;/h2&gt;
&lt;p&gt;把&amp;quot;行为&amp;quot;作为参数传递，让代码更灵活。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 没有函数指针: 每有一种排序规则就要写一个函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sort_ascending&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; arr, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; n);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sort_descending&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; arr, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; n);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 有函数指针: 一个排序函数,规则由调用方决定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sort&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; arr, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; n, &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;compare)(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="函数指针基础语法"&gt;函数指针基础语法&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 定义两个比较函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ascending&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; a &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; b; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;descending&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b) { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; a &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; b; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 参数是函数指针: bool (*compare)(int, int)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sort&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; arr, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; n, &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;compare)(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; n &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;span style="color:#f92672"&gt;++&lt;/span&gt;i)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; j &lt;span style="color:#f92672"&gt;=&lt;/span&gt; i &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; j &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; n; &lt;span style="color:#f92672"&gt;++&lt;/span&gt;j)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (compare(arr[j], arr[i])) &lt;span style="color:#75715e"&gt;// 调用比较函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;swap(arr[i], arr[j]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; arr[] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sort(arr, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, ascending); &lt;span style="color:#75715e"&gt;// 传函数名(自动转成指针)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// sort(arr, 5, &amp;amp;ascending); // 显式取地址也可以
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sort(arr, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, descending);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x : arr) std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; x &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;语法记忆&lt;/strong&gt;：&lt;code&gt;bool (*compare)(int, int)&lt;/code&gt; —— &lt;code&gt;*compare&lt;/code&gt; 是函数名，&lt;code&gt;(int,int)&lt;/code&gt; 是参数，&lt;code&gt;bool&lt;/code&gt; 是返回类型。不加括号 &lt;code&gt;bool *compare(...)&lt;/code&gt; 就变成返回指针的函数了。&lt;/p&gt;</description></item><item><title>C++ 基础遗漏知识点：bool、sizeof、auto、nullptr 与 static</title><link>https://www.sylgalaxy.xyz/posts/cpp-fundamentals-gotchas/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-fundamentals-gotchas/</guid><description>&lt;p&gt;容易被忽略但常出问题的基础语法点：&lt;code&gt;bool&lt;/code&gt; 与 &lt;code&gt;boolalpha&lt;/code&gt;、&lt;code&gt;sizeof&lt;/code&gt; 的指针陷阱、&lt;code&gt;auto&lt;/code&gt; 的 const 剥离、&lt;code&gt;nullptr&lt;/code&gt; 与 &lt;code&gt;static&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="1-bool-类型与-boolalpha"&gt;1. bool 类型与 boolalpha&lt;/h2&gt;
&lt;h3 id="核心规则"&gt;核心规则&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;场景&lt;/th&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;bool b = true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;输出 &lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;默认输出数字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bool b = false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;输出 &lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;默认输出数字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bool b = -8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;输出 &lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;非零即为 true&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bool b = 0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;输出 &lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;零即为 false&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="boolalpha-操纵符"&gt;boolalpha 操纵符&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;std::boolalpha&lt;/code&gt; 可以让 &lt;code&gt;cout&lt;/code&gt; 输出 &lt;code&gt;true/false&lt;/code&gt; 而不是 &lt;code&gt;1/0&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; std;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; isTrue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 默认输出（数字）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;默认: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; isTrue &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 输出: 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 使用 boolalpha（文字）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; boolalpha;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;boolalpha: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; isTrue &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 输出: true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 非零值也为 true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;-8 转 bool: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; b &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 输出: true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="常见陷阱"&gt;常见陷阱&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 陷阱1：非零即为 true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; b1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; b2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; b3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.001&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; b4 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// false (C++11)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 陷阱2：bool 与整数混合运算
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true &lt;span style="color:#f92672"&gt;+&lt;/span&gt; true; &lt;span style="color:#75715e"&gt;// a = 2（true 被提升为 1）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// b = 10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="2-sizeof-运算符"&gt;2. sizeof 运算符&lt;/h2&gt;
&lt;h3 id="基本用法"&gt;基本用法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; std;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;char: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;short: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;short&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;int: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;long: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;long&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 4 或 8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;long long: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;long&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;long&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;float: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;float&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;double: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;double&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 数组
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; arr[&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;int[10]: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(arr) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 40
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; p;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;int*: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(p) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 4 或 8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="动态数组的-sizeof-陷阱"&gt;动态数组的 sizeof 陷阱&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; arr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(arr) &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl; &lt;span style="color:#75715e"&gt;// 输出 4 或 8（指针大小，不是数组大小！）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 正确获取动态数组大小：需要额外传参或用 vector
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="3-auto-关键字c11"&gt;3. auto 关键字（C++11）&lt;/h2&gt;
&lt;h3 id="基本用法-1"&gt;基本用法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// int
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.14&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// double
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; z &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// const char*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; flag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; true; &lt;span style="color:#75715e"&gt;// bool
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 推荐用于复杂类型
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;map&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;vector&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; v &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; it &lt;span style="color:#f92672"&gt;=&lt;/span&gt; v.begin(); &lt;span style="color:#75715e"&gt;// std::vector&amp;lt;int&amp;gt;::iterator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;map&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;string, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; m;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; pair &lt;span style="color:#f92672"&gt;=&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;make_pair(&lt;span style="color:#e6db74"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="注意事项"&gt;注意事项&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// auto 会忽略顶层 const
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a; &lt;span style="color:#75715e"&gt;// b 是 int，不是 const int
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a; &lt;span style="color:#75715e"&gt;// c 是 const int
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 引用形式的 auto 才保留底层 const
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; ref &lt;span style="color:#f92672"&gt;=&lt;/span&gt; a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; ref2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ref; &lt;span style="color:#75715e"&gt;// ref2 是 int 拷贝——普通 auto 剥离引用,连同底层 const 一起丢
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; ref3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ref; &lt;span style="color:#75715e"&gt;// ref3 是 const int&amp;amp;——auto&amp;amp; 保留底层 const(不能改 *ref3)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="4-nullptrc11"&gt;4. nullptr（C++11）&lt;/h2&gt;
&lt;h3 id="与-null-的区别"&gt;与 NULL 的区别&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// NULL 在 C++ 中可能是 0 或 (void*)0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;func&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;func&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;char&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;func(NULL); &lt;span style="color:#75715e"&gt;// 编译错误！歧义
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;func(&lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// OK，调用 func(char*)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="最佳实践"&gt;最佳实践&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 初始化指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; p &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 判断指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (p &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 使用 p
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 函数参数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt; ptr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (ptr &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="5-const-与-constexpr简记"&gt;5. const 与 constexpr（简记）&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;const&lt;/th&gt;
&lt;th&gt;constexpr&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;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// OK
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;constexpr&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// OK，编译期常量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// constexpr 函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;constexpr&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;square&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; n) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; n &lt;span style="color:#f92672"&gt;*&lt;/span&gt; n;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;constexpr&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; val &lt;span style="color:#f92672"&gt;=&lt;/span&gt; square(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 编译期计算
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;const&lt;/code&gt; 与 &lt;code&gt;constexpr&lt;/code&gt; 的完整对比、&lt;code&gt;constexpr&lt;/code&gt; 函数、&lt;code&gt;if constexpr&lt;/code&gt;、C++20 的 &lt;code&gt;consteval&lt;/code&gt;/&lt;code&gt;constinit&lt;/code&gt;，见另一篇《C++ namespace、const 与 constexpr 知识点总结》。&lt;/p&gt;</description></item><item><title>C++ 网络编程基础：Socket API 与 TCP 通信</title><link>https://www.sylgalaxy.xyz/posts/cpp-socket-networking-basics/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-socket-networking-basics/</guid><description>&lt;p&gt;围绕 Socket API 与 TCP/UDP 通信的核心概念、函数对照、示例代码与常见坑。&lt;/p&gt;
&lt;h2 id="核心概念速查"&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;th&gt;关键点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Socket&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;TCP&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;UDP&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;sockaddr&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;通用地址结构&lt;/td&gt;
&lt;td&gt;IPv4/IPv6 统一接口&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;code&gt;htons()&lt;/code&gt; &lt;code&gt;htonl()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="tcp-三次握手与四次挥手"&gt;TCP 三次握手与四次挥手&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;三次握手(建立连接):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──SYN────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ◀─SYN+Ack─ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──Ack────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;四次挥手(关闭连接):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──FIN────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ◀─Ack───── Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ◀─FIN───── Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Client ──Ack────▶ Server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="tcp-客户端-服务器模型"&gt;TCP 客户端-服务器模型&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;服务器: socket() → bind() → listen() → accept() → recv/send → close()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;客户端: socket() → connect() → send/recv → close()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="核心函数对照表"&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;th&gt;参数要点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;创建套接字&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AF_INET, SOCK_STREAM, 0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bind()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;绑定地址&lt;/td&gt;
&lt;td&gt;套接字 + sockaddr_in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;listen()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;监听连接&lt;/td&gt;
&lt;td&gt;backlog 队列长度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;accept()&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;connect()&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;send/recv()&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;htons/htonl()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;主机→网络字节序&lt;/td&gt;
&lt;td&gt;short/long&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ntohs/ntohl()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;网络→主机字节序&lt;/td&gt;
&lt;td&gt;short/long&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="从-qt-到原生-socket"&gt;从 Qt 到原生 Socket&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Qt 写法&lt;/th&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;server.listen(QHostAddress::Any, 8080)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;socket()&lt;/code&gt; + &lt;code&gt;bind()&lt;/code&gt; + &lt;code&gt;listen()&lt;/code&gt; 三步&lt;/td&gt;
&lt;td&gt;Qt 一行帮你做三件事&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;newConnection&lt;/code&gt; 信号 → &lt;code&gt;nextPendingConnection()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;accept()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Qt 信号通知;原生阻塞死等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket-&amp;gt;connectToHost(&amp;quot;ip&amp;quot;, port)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;inet_pton()&lt;/code&gt; + &lt;code&gt;connect()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;IP 解析要自己做&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket-&amp;gt;write(bytes)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;send(fd, buf, len, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;返回值要检查,可能只发一半&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;readyRead&lt;/code&gt; 信号 → &lt;code&gt;readAll()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;recv(fd, buf, size, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;没有&amp;quot;就绪通知&amp;quot;,直接阻塞读&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;errorOccurred&lt;/code&gt; / &lt;code&gt;stateChanged&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;检查返回值 + &lt;code&gt;errno&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;错误要手动判断&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QUdpSocket::writeDatagram/readDatagram&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sendto()/recvfrom()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;多一个对端地址参数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QHostAddress(&amp;quot;127.0.0.1&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sockaddr_in&lt;/code&gt; + &lt;code&gt;inet_pton()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字符串 IP 手动转结构体&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;端口字节序自动处理&lt;/td&gt;
&lt;td&gt;必须自己 &lt;code&gt;htons()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Qt 内部帮你转了&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;核心差异&lt;/strong&gt;：Qt 信号槽背后是「事件循环 + 就绪通知」(reactor 模式)。原生编程没有这个循环——要么阻塞死等，要么用线程，要么用 &lt;code&gt;select/epoll&lt;/code&gt; 自己搭事件循环。学原生网络的本质，就是把 Qt 隐藏的三件事（&lt;strong&gt;fd 管理、字节序、事件分发&lt;/strong&gt;）亲手做一遍。&lt;/p&gt;</description></item><item><title>C++ 线程基础：std::thread、join/detach 与传参陷阱</title><link>https://www.sylgalaxy.xyz/posts/cpp-thread-basics/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-thread-basics/</guid><description>&lt;p&gt;&lt;code&gt;std::thread&lt;/code&gt; 的创建方式、join 与 detach 的语义、传参陷阱与常见坑。同步机制（互斥锁、条件变量、原子操作）见另一篇并发笔记。&lt;/p&gt;
&lt;h2 id="核心概念速查"&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;th&gt;关键点&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;独立运行的程序实例&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;std::thread&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C++11 线程库&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#include &amp;lt;thread&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;join&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;detach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;分离线程&lt;/td&gt;
&lt;td&gt;后台运行,不再可 join&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="进程-vs-线程"&gt;进程 vs 线程&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;th&gt;线程&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;崩溃影响&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;高并发、I/O 密集&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="创建线程"&gt;创建线程&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;thread&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hello&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Hello from thread&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式1: 无参函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt; t1(hello);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式2: lambda
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt; t2([]{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Hello from lambda&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式3: 带参函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; print_num &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [](&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; n) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Number: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; n &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt; t3(print_num, &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t1.join();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t2.join();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; t3.join();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="join-与-detach"&gt;join 与 detach&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;th&gt;何时用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;join()&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;detach()&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;p&gt;&lt;strong&gt;陷阱&lt;/strong&gt;：线程要么 join 要么 detach，都不做 → 析构时 &lt;code&gt;std::terminate()&lt;/code&gt; 崩溃。detach 的线程访问已销毁的对象 → 未定义行为。&lt;/p&gt;</description></item><item><title>C++ 项目约定：目录结构、依赖管理、构建与 Git</title><link>https://www.sylgalaxy.xyz/posts/env-project-convention/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/env-project-convention/</guid><description>&lt;p&gt;所谓「约定」= 一套&lt;strong&gt;项目结构规范 + 依赖管理规范&lt;/strong&gt;：以后不管做什么项目，都按这个套路来，不用每次重新想。&lt;/p&gt;
&lt;p&gt;适用背景：&lt;strong&gt;Windows（VS2022）只做 Boost + OpenCV，不做 Qt；Qt 开发放在 Linux（Ubuntu 虚拟机/服务器）&lt;/strong&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;文中 &lt;code&gt;&amp;lt;OpenCV安装目录&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;Boost根目录&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;项目根目录&amp;gt;&lt;/code&gt; 为占位符，替换成本机实际目录即可。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="一总体原则"&gt;一、总体原则&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;三句话：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CMake 是唯一的构建系统&lt;/strong&gt;，不碰 qmake、不碰手动 &lt;code&gt;.vcxproj&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;依赖一律走环境变量 + &lt;code&gt;find_package&lt;/code&gt;&lt;/strong&gt;，不在 &lt;code&gt;CMakeLists.txt&lt;/code&gt; 里硬编码路径。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows 端 IDE 是 VS2022 + CMake 项目模式&lt;/strong&gt;；Linux 端用 Qt Creator 或 VS Code。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="二目录结构约定windows-端"&gt;二、目录结构约定（Windows 端）&lt;/h2&gt;
&lt;p&gt;每个项目固定长这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;项目根目录&amp;gt;\&amp;lt;项目名&amp;gt;\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── CMakeLists.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── CMakePresets.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── CMakeUserPresets.json # 本地预设（不提交 Git）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── README.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── src\ # 源码
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── main.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── core\ # Boost 业务逻辑
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── Service.h
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ └── Service.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── vision\ # OpenCV 图像处理
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── ImageProcessor.h
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── ImageProcessor.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── include\ # 对外头文件（可选）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── resources\ # 静态资源、图片（可选）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── tests\ # 测试代码（可选）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── third_party\ # 第三方源码（可选，一般不用）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── out\ # 构建输出（不提交 Git）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── build\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── debug\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── release\
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键点：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>channel 详解</title><link>https://www.sylgalaxy.xyz/posts/go-03-02-channel/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-02-channel/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 里你得自己造「互斥锁 + 条件变量 + 队列」才能做到的线程通信，Go 用一个 channel 就把它变成了语言级原语&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;channel（通道）是 Go 并发模型的&lt;strong&gt;核心&lt;/strong&gt;，它的口号是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;「Do not communicate by sharing memory; instead, share memory by communicating.」&lt;/strong&gt; —— 不要通过共享内存来通信，而要通过通信来共享内存。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;一个 channel 就是一个&lt;strong&gt;带类型的 FIFO 队列&lt;/strong&gt;，goroutine 之间通过它发送 / 接收数据，同时天然完成了&lt;strong&gt;同步&lt;/strong&gt;（谁等谁、什么时候等）与&lt;strong&gt;数据传递&lt;/strong&gt;两件事。&lt;/p&gt;
&lt;p&gt;作为 C++ 开发者，你过去写线程同步大概是这样：&lt;code&gt;std::mutex&lt;/code&gt; 保护共享数据 + &lt;code&gt;std::condition_variable&lt;/code&gt; 通知 + &lt;code&gt;std::queue&lt;/code&gt; 存数据 + 各种 &lt;code&gt;unique_lock&lt;/code&gt;。而 Go 把这三件套打包成了一个 channel：&lt;strong&gt;发送阻塞、接收阻塞、容量限制、关闭通知&lt;/strong&gt;全部内建，而且它在&lt;strong&gt;语言层面&lt;/strong&gt;保证了 channel 操作本身的线程安全。&lt;/p&gt;
&lt;p&gt;本笔记覆盖：创建、无缓冲 / 有缓冲的阻塞语义、单向 channel、关闭与 &lt;code&gt;range&lt;/code&gt; 消费、nil channel、死锁场景，以及「channel 当锁」的奇技淫巧。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::queue&amp;lt;T&amp;gt;&lt;/code&gt; + &lt;code&gt;std::mutex&lt;/code&gt; + &lt;code&gt;std::condition_variable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ch := make(chan T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 一条语句搞定，且是语言级原语&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;code&gt;make(chan T)&lt;/code&gt;（默认无缓冲）&lt;/td&gt;
&lt;td&gt;无缓冲 channel 天然同步：发=等收&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;有缓冲队列&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::queue&lt;/code&gt; + 信号量限制&lt;/td&gt;
&lt;td&gt;&lt;code&gt;make(chan T, 5)&lt;/code&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;code&gt;queue.push(x); cv.notify_one();&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ch &amp;lt;- x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;-&lt;/code&gt; 方向右：发送&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;接收操作&lt;/td&gt;
&lt;td&gt;&lt;code&gt;queue.pop();&lt;/code&gt;（空时等 cv）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x := &amp;lt;-ch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;-&lt;/code&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;td&gt;Go 不需要手写谓词循环&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;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;code&gt;close(ch)&lt;/code&gt;，只能发送方关闭&lt;/td&gt;
&lt;td&gt;关闭后 range 自动结束&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;td&gt;Go 收发都允许并发，无需额外锁&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;非阻塞操作&lt;/td&gt;
&lt;td&gt;try_lock / 检查队列非空&lt;/td&gt;
&lt;td&gt;&lt;code&gt;select + default&lt;/code&gt;（下篇讲）&lt;/td&gt;
&lt;td&gt;select 是非阻塞收发的标准姿势&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-创建-channelmake"&gt;3.1 创建 channel：&lt;code&gt;make&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 无缓冲 channel：接收方和发送方必须同时准备好，相当于一次「握手」&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ch1&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 有缓冲 channel：容量为 5，缓冲不满时发送不阻塞&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ch2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 只声明不 make 的 channel 是 nil channel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ch3&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ch3&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// true（nil channel 不能收发，见 3.7）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ch1&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ch2&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// false, false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;ch1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;ch2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;C++ 对照&lt;/strong&gt;：&lt;code&gt;make(chan int)&lt;/code&gt; 既有「分配」又有「初始化」两层含义，像 &lt;code&gt;std::make_shared&amp;lt;T&amp;gt;()&lt;/code&gt;。注意这里返回的是 &lt;strong&gt;channel 本身&lt;/strong&gt;，不是一个指针——但你如果 &lt;code&gt;ch2 := make(chan int)&lt;/code&gt; 再 &lt;code&gt;ch2 = ch2&lt;/code&gt;，传递的都是同一个底层通道的引用，多个 goroutine 共享它时不需要再加锁。&lt;/p&gt;</description></item><item><title>CLI 工具 flag 与 cobra</title><link>https://www.sylgalaxy.xyz/posts/go-05-01-cli-flag-cobra/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-05-01-cli-flag-cobra/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 Boost.Program_options / CLI11 到 Go：标准库 flag 包入门，再上手 cobra 这个事实标准的命令行框架&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;命令行工具（CLI）是 Go 最擅长的领域之一：编译出来是单一静态二进制，启动快、分发简单，天然适合写 &lt;code&gt;git&lt;/code&gt; / &lt;code&gt;docker&lt;/code&gt; 这类开发者工具。Go 在命令行的「外挂」上做了很多设计——&lt;code&gt;os.Args&lt;/code&gt; 给你原始参数，标准库 &lt;code&gt;flag&lt;/code&gt; 包给你简单的 &lt;code&gt;-name value&lt;/code&gt; 解析，而 &lt;code&gt;spf13/cobra&lt;/code&gt;（Kubernetes、Hugo、Docker CLI 大量使用）则提供子命令、flag 继承、自动帮助和 shell 补全的完整方案。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：C++ 里解析命令行要么手写循环扫 &lt;code&gt;argv&lt;/code&gt;，要么拉 Boost.Program_options / CLI11；Go 的路径是「标准库 flag 够用即用，复杂命令行直接上 cobra」。cobra 的「命令树」思想对 C++ 开发者来说很像「用对象组合搭一棵命令路由树」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;int main(int argc, char* argv[])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func main()&lt;/code&gt; + &lt;code&gt;os.Args&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;os.Args[0]&lt;/code&gt; 是程序名，Go 是切片可遍历&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;参数解析库&lt;/td&gt;
&lt;td&gt;Boost.Program_options / CLI11&lt;/td&gt;
&lt;td&gt;&lt;code&gt;flag&lt;/code&gt;（标准库）&lt;/td&gt;
&lt;td&gt;flag 零依赖，但功能简单&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;子命令框架&lt;/td&gt;
&lt;td&gt;自己搭 / CLI11&lt;/td&gt;
&lt;td&gt;&lt;code&gt;github.com/spf13/cobra&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;cobra 是事实标准（k8s/gh/hugo 都用）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型自动转换&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boost::lexical_cast&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;flag 绑定即转换&lt;/td&gt;
&lt;td&gt;&lt;code&gt;flag.Int&lt;/code&gt; 自动转，无需显式 cast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;帮助文本&lt;/td&gt;
&lt;td&gt;手动拼接打印&lt;/td&gt;
&lt;td&gt;flag / cobra 自动生成&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-h&lt;/code&gt; / &lt;code&gt;--help&lt;/code&gt; 开箱即用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;长短选项&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-v&lt;/code&gt; / &lt;code&gt;--verbose&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-v&lt;/code&gt; / &lt;code&gt;--verbose&lt;/code&gt; 等价&lt;/td&gt;
&lt;td&gt;flag 单双横线都认；布尔无需值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;子命令树&lt;/td&gt;
&lt;td&gt;无标准方案&lt;/td&gt;
&lt;td&gt;cobra &lt;code&gt;AddCommand&lt;/code&gt; 层层挂载&lt;/td&gt;
&lt;td&gt;命令即对象，可嵌套&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shell 补全&lt;/td&gt;
&lt;td&gt;无标准方案&lt;/td&gt;
&lt;td&gt;cobra &lt;code&gt;completion&lt;/code&gt; 命令&lt;/td&gt;
&lt;td&gt;生成 bash/zsh/fish 脚本&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;解析失败行为&lt;/td&gt;
&lt;td&gt;抛异常 / 返回错误码&lt;/td&gt;
&lt;td&gt;flag 默认 &lt;code&gt;ExitOnError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可切换到 &lt;code&gt;ContinueOnError&lt;/code&gt; 自己处理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-osargs--原始参数切片"&gt;3.1 os.Args —— 原始参数切片&lt;/h3&gt;
&lt;p&gt;任何命令行的起点。和 C++ 的 &lt;code&gt;argc/argv&lt;/code&gt; 相比，Go 把它做成了普通切片，不用数个数、不用指针算术：&lt;/p&gt;</description></item><item><title>CMake 工程模板：VS2022 + Boost（静态库）</title><link>https://www.sylgalaxy.xyz/posts/env-cmake-boost-template/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/env-cmake-boost-template/</guid><description>&lt;p&gt;这是一个可直接复制的 Boost 工程模板（VS2022 + CMake + Ninja）。&lt;strong&gt;模板的作用&lt;/strong&gt;：新建 Boost 项目时不用每次从零配置——复制模板、改项目名、加源文件即可。整套约定是：CMake 为唯一构建系统、依赖走环境变量 + &lt;code&gt;find_package&lt;/code&gt;、构建输出在 &lt;code&gt;out/build/&lt;/code&gt;、不写死路径。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;前置环境变量：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BOOST_ROOT = &amp;lt;Boost根目录&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Boost 是&lt;strong&gt;静态库&lt;/strong&gt;（vc143 构建），不用加 PATH，运行时不需要 dll&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id="一目录结构"&gt;一、目录结构&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;项目根目录&amp;gt;\BoostTemplate\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── CMakeLists.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── CMakePresets.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── src\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── main.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── out\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── build\
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="二cmakeliststxt复制到项目根目录"&gt;二、CMakeLists.txt（复制到项目根目录）&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cmake" data-lang="cmake"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cmake_minimum_required(&lt;span style="color:#e6db74"&gt;VERSION&lt;/span&gt; &lt;span style="color:#e6db74"&gt;3.20&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;project(&lt;span style="color:#e6db74"&gt;BoostTemplate&lt;/span&gt; &lt;span style="color:#e6db74"&gt;LANGUAGES&lt;/span&gt; &lt;span style="color:#e6db74"&gt;CXX&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;CMAKE_CXX_STANDARD&lt;/span&gt; &lt;span style="color:#e6db74"&gt;17&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;CMAKE_CXX_STANDARD_REQUIRED&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ---------- Boost ----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# BOOST_ROOT 由 CMakePresets.json 从环境变量注入，这里不写路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;Boost_NO_SYSTEM_PATHS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 只从 BOOST_ROOT 找，不扫系统路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;Boost_USE_STATIC_LIBS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 用静态库（vc143 静态构建）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;Boost_USE_MULTITHREADED&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;) &lt;span style="color:#75715e"&gt;# 多线程版本
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;find_package(&lt;span style="color:#e6db74"&gt;Boost&lt;/span&gt; &lt;span style="color:#e6db74"&gt;1.81&lt;/span&gt; &lt;span style="color:#e6db74"&gt;REQUIRED&lt;/span&gt; &lt;span style="color:#e6db74"&gt;COMPONENTS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;filesystem&lt;/span&gt; &lt;span style="color:#e6db74"&gt;system&lt;/span&gt; &lt;span style="color:#e6db74"&gt;thread&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ---------- 源文件 ----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;SOURCES&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;src/main.cpp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add_executable(&lt;span style="color:#f92672"&gt;${&lt;/span&gt;PROJECT_NAME&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;SOURCES&lt;span style="color:#f92672"&gt;}&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target_include_directories(&lt;span style="color:#f92672"&gt;${&lt;/span&gt;PROJECT_NAME&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#e6db74"&gt;PRIVATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;CMAKE_CURRENT_SOURCE_DIR&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/src&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target_link_libraries(&lt;span style="color:#f92672"&gt;${&lt;/span&gt;PROJECT_NAME&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#e6db74"&gt;PRIVATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;Boost::filesystem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;Boost::system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;Boost::thread&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三cmakepresetsjson复制到项目根目录"&gt;三、CMakePresets.json（复制到项目根目录）&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;configurePresets&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;generator&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Ninja&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;binaryDir&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;${sourceDir}/out/build/${presetName}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;cacheVariables&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CMAKE_BUILD_TYPE&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Debug&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;BOOST_ROOT&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;$env{BOOST_ROOT}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Boost_NO_SYSTEM_PATHS&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Boost_USE_STATIC_LIBS&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Boost_USE_MULTITHREADED&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;release&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;inherits&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;cacheVariables&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CMAKE_BUILD_TYPE&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Release&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;buildPresets&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;configurePreset&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;release&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;configurePreset&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;release&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;版本待核实：预设文件 &lt;code&gt;&amp;quot;version&amp;quot;: 3&lt;/code&gt; 与 &lt;code&gt;CMakeLists.txt&lt;/code&gt; 里 &lt;code&gt;cmake_minimum_required(VERSION 3.20)&lt;/code&gt; 的版本要求是否匹配（version 3 预设需较新的 CMake），首次配置前请确认本机 / VS2022 自带 CMake 的实际版本。&lt;/p&gt;</description></item><item><title>CMake 工程模板：VS2022 + OpenCV 4.10</title><link>https://www.sylgalaxy.xyz/posts/env-cmake-opencv-template/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/env-cmake-opencv-template/</guid><description>&lt;p&gt;这是一个可直接复制的 OpenCV 工程模板（VS2022 + CMake + Ninja）。&lt;strong&gt;模板的作用&lt;/strong&gt;：新建 OpenCV 项目时不用每次手动加 include/lib 路径——复制模板、改项目名、加源文件即可。整套约定是：CMake 为唯一构建系统、依赖走环境变量 + &lt;code&gt;find_package&lt;/code&gt;、构建输出在 &lt;code&gt;out/build/&lt;/code&gt;、不写死路径。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;前置环境变量：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OpenCV_DIR = &amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\lib&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;PATH 追加：&lt;code&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\bin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id="一目录结构"&gt;一、目录结构&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;项目根目录&amp;gt;\OpenCVTemplate\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── CMakeLists.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── CMakePresets.json
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── src\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── main.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── out\
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── build\
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="二cmakeliststxt复制到项目根目录"&gt;二、CMakeLists.txt（复制到项目根目录）&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cmake" data-lang="cmake"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cmake_minimum_required(&lt;span style="color:#e6db74"&gt;VERSION&lt;/span&gt; &lt;span style="color:#e6db74"&gt;3.20&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;project(&lt;span style="color:#e6db74"&gt;OpenCVTemplate&lt;/span&gt; &lt;span style="color:#e6db74"&gt;LANGUAGES&lt;/span&gt; &lt;span style="color:#e6db74"&gt;CXX&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;CMAKE_CXX_STANDARD&lt;/span&gt; &lt;span style="color:#e6db74"&gt;17&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;CMAKE_CXX_STANDARD_REQUIRED&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ---------- OpenCV ----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# OpenCV_DIR 由 CMakePresets.json 从环境变量注入，这里不写路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;find_package(&lt;span style="color:#e6db74"&gt;OpenCV&lt;/span&gt; &lt;span style="color:#e6db74"&gt;REQUIRED&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ---------- 源文件 ----------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;SOURCES&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;src/main.cpp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add_executable(&lt;span style="color:#f92672"&gt;${&lt;/span&gt;PROJECT_NAME&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;SOURCES&lt;span style="color:#f92672"&gt;}&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target_include_directories(&lt;span style="color:#f92672"&gt;${&lt;/span&gt;PROJECT_NAME&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#e6db74"&gt;PRIVATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;CMAKE_CURRENT_SOURCE_DIR&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/src&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;OpenCV_INCLUDE_DIRS&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target_link_libraries(&lt;span style="color:#f92672"&gt;${&lt;/span&gt;PROJECT_NAME&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#e6db74"&gt;PRIVATE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;OpenCV_LIBS&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三cmakepresetsjson复制到项目根目录"&gt;三、CMakePresets.json（复制到项目根目录）&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;configurePresets&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;generator&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Ninja&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;binaryDir&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;${sourceDir}/out/build/${presetName}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;cacheVariables&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CMAKE_BUILD_TYPE&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Debug&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;OpenCV_DIR&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;$env{OpenCV_DIR}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;release&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;inherits&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;cacheVariables&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;CMAKE_BUILD_TYPE&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Release&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;buildPresets&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;configurePreset&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;debug&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;release&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;configurePreset&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;release&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;版本待核实：预设文件 &lt;code&gt;&amp;quot;version&amp;quot;: 3&lt;/code&gt; 与 &lt;code&gt;CMakeLists.txt&lt;/code&gt; 里 &lt;code&gt;cmake_minimum_required(VERSION 3.20)&lt;/code&gt; 的版本要求是否匹配（version 3 预设需较新的 CMake），首次配置前请确认本机 / VS2022 自带 CMake 的实际版本。&lt;/p&gt;</description></item><item><title>context 超时取消与传值</title><link>https://www.sylgalaxy.xyz/posts/go-03-06-context/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-06-context/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 没有直接对应的东西——它最接近 std::jthread 的 stop_token：一个穿过调用链的「取消令牌 + 截止时间 + 键值袋」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;context.Context&lt;/code&gt;（标准库 &lt;code&gt;context&lt;/code&gt; 包）是 Go 并发中&lt;strong&gt;传播取消信号、截止时间与请求级数据&lt;/strong&gt;的载体。它贯穿整个标准库（HTTP 请求、数据库、RPC），是每一个「可能被取消的耗时代码」的标配第一参数。&lt;/p&gt;
&lt;p&gt;它解决 C++ 里三个长期痛点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;传递取消信号&lt;/strong&gt;：深调用链中，任何一层想取消整条链，怎么办？C++ 用 &lt;code&gt;std::atomic&amp;lt;bool&amp;gt;&lt;/code&gt; 到处传 + 检查，或 &lt;code&gt;std::jthread&lt;/code&gt; 的 &lt;code&gt;stop_token&lt;/code&gt;。Go 里就是 &lt;code&gt;ctx.Done()&lt;/code&gt; + 广播。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;传递截止时间&lt;/strong&gt;：每个函数都检查「现在是不是超时了」很烦。Go 里 &lt;code&gt;context.WithDeadline&lt;/code&gt; 一路带过去，子任务自己查 &lt;code&gt;ctx.Done()&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;传递请求级数据&lt;/strong&gt;：分布式的 trace id、用户信息等「横切数据」，Go 用 &lt;code&gt;WithValue&lt;/code&gt; 携带，避免每个函数都加参。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;strong&gt;&lt;code&gt;context.Context&lt;/code&gt; 只做三件事：取消（Cancel）、截止（Deadline/Timeout）、传值（Value）。&lt;/strong&gt; 它不是「任意全局状态袋」，不该往里塞业务对象；也不是给每个函数都强加的仪式，而是给「可能被取消的耗时代码」用的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::stop_token&lt;/code&gt; / 手写 &lt;code&gt;atomic&amp;lt;bool&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ctx.Done()&lt;/code&gt; + 树形传播&lt;/td&gt;
&lt;td&gt;Go 一次 cancel 广播整棵子树&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;超时取消&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::stoptoken&lt;/code&gt; + 手算时间&lt;/td&gt;
&lt;td&gt;&lt;code&gt;context.WithTimeout(ctx, 3*time.Second)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一行完成「到时自动 cancel」&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;截止时间&lt;/td&gt;
&lt;td&gt;&lt;code&gt;steady_clock::now() + d&lt;/code&gt; 自己算&lt;/td&gt;
&lt;td&gt;&lt;code&gt;context.WithDeadline(ctx, t)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 语义是绝对时刻&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;手动取消&lt;/td&gt;
&lt;td&gt;手写 &lt;code&gt;atomic&amp;lt;bool&amp;gt;&lt;/code&gt; + 到处检查&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cancelFunc()&lt;/code&gt;（WithCancel 返回）&lt;/td&gt;
&lt;td&gt;cancel 是「广播」，不只本层&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;关联请求数据&lt;/td&gt;
&lt;td&gt;线程局部 / 全局 map（危险）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;context.WithValue(parent, key, val)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 类型安全 + 随 ctx 走&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;goroutine 收尾&lt;/td&gt;
&lt;td&gt;&lt;code&gt;jthread.request_stop()&lt;/code&gt; + join&lt;/td&gt;
&lt;td&gt;&lt;code&gt;select { case &amp;lt;-ctx.Done(): ... }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 惯例：非主路径用 select 监听取消&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;code&gt;ctx.Err()&lt;/code&gt; → &lt;code&gt;context.Canceled&lt;/code&gt; / &lt;code&gt;DeadlineExceeded&lt;/code&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;无（要么传 token，要么全局）&lt;/td&gt;
&lt;td&gt;函数第一参数约定&lt;/td&gt;
&lt;td&gt;Go 靠约定 + vet 检查不传 nil&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-两个根contextbackground-与-contexttodo"&gt;3.1 两个根：&lt;code&gt;context.Background()&lt;/code&gt; 与 &lt;code&gt;context.TODO()&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Background：程序的「根上下文」，所有 context 树的起点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Background&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Background Err =&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// nil（永远不会被取消）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Background Done =&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Done&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// nil channel（永不关闭）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// TODO：还没想好用哪个 context 时的占位，语义同 Background&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;context&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TODO&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;TODO 等价于 Background:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt;() &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;ctx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;todo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;规则&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>dsh-image-analyze</title><link>https://www.sylgalaxy.xyz/posts/ai-dsh-image-analyze-readme/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/ai-dsh-image-analyze-readme/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DSH（DeepSeek Harness）插件：让纯文本模型也能&amp;quot;看图&amp;quot;。&lt;/strong&gt;
图片、截图、PDF、Word 文档——统一路由到视觉模型（默认 &lt;code&gt;mimo-v2.5&lt;/code&gt;）分析，对话模型只负责文字推理。全程同一供应商契约，按需付费。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="#"&gt;English&lt;/a&gt; · 中文&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="-特性"&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;strong&gt;四种图片入口&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;指定路径 / &amp;ldquo;分析最新截图&amp;rdquo;（免路径）/ 多张一次 / 桥接粘贴（配合 dsh-image-bridge）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📄 &lt;strong&gt;文档解析&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PDF 逐页渲染（PyMuPDF）、Word(.docx) 解包内嵌图，一次送视觉模型分析&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;code&gt;opencode-go&lt;/code&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;code&gt;mimo-v2.5&lt;/code&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;code&gt;relay&lt;/code&gt;（结构化视觉数据：OCR/布局/颜色/SVG）vs &lt;code&gt;direct&lt;/code&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;小文件直跳 + PNG 像素方差检测，误触的空捕获不会浪费一次调用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📋 &lt;strong&gt;来源可见&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;每次分析返回&amp;quot;分析来源&amp;quot;清单，明确指出实际看了哪些文件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔧 &lt;strong&gt;零依赖&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;插件本体纯 ESM、不 import 任何 &lt;code&gt;@deepseek-ai&lt;/code&gt; 包，本地安装无需 npm registry；文档解析仅需系统 Python&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-架构与工作原理"&gt;🏗 架构与工作原理&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;┌─ 图片入口 ─────────────────────────────────────────────┐
│ ① 指定路径 &amp;#34;分析 D:\xx\img.png&amp;#34; │
│ ② 最新截图 &amp;#34;分析最新截图 / 最新两张截图&amp;#34;（免路径） │
│ ③ 粘贴桥接 dsh-image-bridge 落盘 → [图片附件] 标记 │
│ ④ 文档 &amp;#34;分析 D:\xx\doc.pdf / report.docx&amp;#34; │
└────────────────────────┬───────────────────────────────┘
▼
analyze_images / analyze_document 工具
│
┌────────────────┼──────────────────┐
▼ ▼ ▼
attachments ctx.llm.stream sources
(持久化图片) provider: opencode-go (来源报告)
model: mimo-v2.5
│
▼
relay 模式 → 结构化视觉数据（OCR/布局/颜色/SVG）→ 对话模型推理
direct 模式 → 视觉模型直接产出最终答案（如 HTML 复刻）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;设计要点&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>encoding/json 与配置文件</title><link>https://www.sylgalaxy.xyz/posts/go-02-05-encoding-json/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-02-05-encoding-json/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 nlohmann/json 到 Go 的 encoding/json：结构体标签驱动的序列化&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 的 &lt;code&gt;encoding/json&lt;/code&gt; 是标准库内置的 JSON 序列化/反序列化包。与 C++ 需要第三方库（nlohmann/json、rapidjson）不同，Go 通过**结构体字段标签（struct tag）**声明式地描述 JSON 映射关系，&lt;code&gt;json.Marshal&lt;/code&gt; / &lt;code&gt;json.Unmarshal&lt;/code&gt; 一键完成转换。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go 的 JSON 哲学是&amp;quot;&lt;strong&gt;结构体即 schema&lt;/strong&gt;&amp;quot;——先用结构体定义数据形状，标签控制字段名、可选性、忽略规则。这也让配置文件读写（JSON/YAML）变得极其自然。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JSON 库&lt;/td&gt;
&lt;td&gt;nlohmann/json 等第三方&lt;/td&gt;
&lt;td&gt;&lt;code&gt;encoding/json&lt;/code&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;code&gt;json j = json::parse(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;json.Unmarshal(data, &amp;amp;v)&lt;/code&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;code&gt;j.dump()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;json.Marshal(v)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;返回 []byte + error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;字段改名&lt;/td&gt;
&lt;td&gt;手动构造&lt;/td&gt;
&lt;td&gt;struct tag &lt;code&gt;`json:&amp;quot;name&amp;quot;`&lt;/code&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;code&gt;`json:&amp;quot;-&amp;quot;`&lt;/code&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;code&gt;omitempty&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;零值不输出&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;动态 JSON&lt;/td&gt;
&lt;td&gt;&lt;code&gt;json::object()&lt;/code&gt; / 数组&lt;/td&gt;
&lt;td&gt;&lt;code&gt;map[string]any&lt;/code&gt; / &lt;code&gt;[]any&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;用 any 容器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;配置文件&lt;/td&gt;
&lt;td&gt;Boost.PropertyTree / YAML 库&lt;/td&gt;
&lt;td&gt;读 JSON 或第三方 YAML（gopkg.in/yaml.v3）&lt;/td&gt;
&lt;td&gt;JSON 为主&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三序列化与反序列化"&gt;三、序列化与反序列化&lt;/h2&gt;
&lt;h3 id="31-基本用法"&gt;3.1 基本用法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;encoding/json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 序列化：结构体 → JSON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Marshal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; panic(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(string(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// {&amp;#34;Name&amp;#34;:&amp;#34;Tom&amp;#34;,&amp;#34;Age&amp;#34;:30}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 反序列化：JSON → 结构体&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;p2&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Unmarshal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;p2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; panic(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%+v\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;p2&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// {Name:Tom Age:30}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-结构体标签关键"&gt;3.2 结构体标签（关键）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Config&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Server&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;server&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 字段名映射为 server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Port&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;port&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 默认 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Debug&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;debug,omitempty&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 零值时省略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Secret&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;-&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 永远不参与 JSON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Tags&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;tags,omitempty&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 空切片省略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Config&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Server&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Secret&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;不输出&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Marshal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(string(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// {&amp;#34;server&amp;#34;:&amp;#34;localhost&amp;#34;,&amp;#34;port&amp;#34;:0}（debug/tags 因 omitempty 省略，port 没有 omitempty 所以零值照样输出，secret 被 json:&amp;#34;-&amp;#34; 忽略）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;标签规则&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>GMP 调度模型</title><link>https://www.sylgalaxy.xyz/posts/go-06-01-gmp/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-06-01-gmp/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 里你要手写线程池、任务队列、负载均衡；Go 用 G/M/P 三件套在运行时层面把它全包了&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;goroutine 不是 OS 线程，它比线程轻几个数量级。让几十万 goroutine 复用少数几个内核线程的，就是本章主角——&lt;strong&gt;GMP 调度模型&lt;/strong&gt;。学完你会明白：&lt;code&gt;go func()&lt;/code&gt; 背后发生了什么、为什么 goroutine 能在系统调用阻塞时&amp;quot;让位&amp;quot;、&lt;code&gt;GOMAXPROCS&lt;/code&gt; 到底是什么、以及 M:N 用户态协程调度器是如何设计的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;strong&gt;G&lt;/strong&gt;（goroutine，任务）、&lt;strong&gt;M&lt;/strong&gt;（Machine，OS 线程，工人）、&lt;strong&gt;P&lt;/strong&gt;（Processor，调度上下文，工位）。P 的数量才是真正同时跑的 &amp;ldquo;线程数&amp;rdquo;，G 挂在 P 的本地队列上排队执行，M 抢到 P 才干活。运行时自动完成了 C++ 里你手写线程池 + 任务队列 + work-stealing 的全部工作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::thread&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;goroutine (G)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::thread&lt;/code&gt; 直接映射 OS 线程，G 是用户态任务&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;线程池&lt;/td&gt;
&lt;td&gt;自写 / &lt;code&gt;BS::thread_pool&lt;/code&gt; 等&lt;/td&gt;
&lt;td&gt;内置 GMP&lt;/td&gt;
&lt;td&gt;Go 运行时自动复用 M，无需自建池&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;任务队列&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::queue&amp;lt;std::function&amp;gt;&lt;/code&gt; + mutex&lt;/td&gt;
&lt;td&gt;P 本地队列 runq&lt;/td&gt;
&lt;td&gt;每个 P 有 256 长的本地队列，另有全局限队列&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;线程数量&lt;/td&gt;
&lt;td&gt;自己定 / &lt;code&gt;std::thread::hardware_concurrency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOMAXPROCS&lt;/code&gt;（默认 = CPU 核数）&lt;/td&gt;
&lt;td&gt;P 的数量决定并行度，M 可多于 P&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;线程阻塞迁移&lt;/td&gt;
&lt;td&gt;无自动机制&lt;/td&gt;
&lt;td&gt;M 阻塞时 P 移交&lt;/td&gt;
&lt;td&gt;系统调用/锁阻塞时，P 被交给其它 M 继续执行 G&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;栈&lt;/td&gt;
&lt;td&gt;固定大小（默认 1~8MB）&lt;/td&gt;
&lt;td&gt;初始 2KB，动态增长&lt;/td&gt;
&lt;td&gt;G 栈可扩容，按需分配&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;让出 CPU&lt;/td&gt;
&lt;td&gt;无（靠 OS 时间片）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;runtime.Gosched()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;G 主动让出 P，避免饿死其它 G&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;抢占&lt;/td&gt;
&lt;td&gt;内核时间片抢占&lt;/td&gt;
&lt;td&gt;运行时信号抢占（Go 1.14+）&lt;/td&gt;
&lt;td&gt;协作式 + 抢占式混合&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;work-stealing&lt;/td&gt;
&lt;td&gt;手写&lt;/td&gt;
&lt;td&gt;内置&lt;/td&gt;
&lt;td&gt;空闲 P 偷其它 P 的队列任务，均衡负载&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;主线程&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int main()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m0&lt;/code&gt; + &lt;code&gt;g0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;运行时专用线程和调度 goroutine&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-三个字母分别是什么"&gt;3.1 三个字母分别是什么&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────────┐
│ GMP 关系示意 │
│ │
│ G (goroutine) M (machine) P (processor) │
│ ┌──────┐ ┌───────┐ ┌─────────────┐ │
│ │ 用户 │ │ 内核 │ │ 调度上下文 │ │
│ │ 代码 │──调度于──→ │ OS线程 │──绑定于──→│ 本地队列 │ │
│ │ 栈G │ │ 栈M │ │ runq[256] │ │
│ └──────┘ └───────┘ └─────────────┘ │
│ 任务 工人 工位 │
└──────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;G（goroutine）&lt;/strong&gt;：一个待执行的函数 + 它的栈 + 上下文（寄存器现场）。创建的每个 &lt;code&gt;go func()&lt;/code&gt; 都对应一个 G。它&lt;strong&gt;只是任务元数据&lt;/strong&gt;，不是执行载体。G 结构体字段很长（&lt;code&gt;src/runtime/runtime2.go&lt;/code&gt;），核心有栈描述 &lt;code&gt;stack&lt;/code&gt;、当前函数 &lt;code&gt;sched&lt;/code&gt;（保存 PC/SP）、状态 &lt;code&gt;atomicstatus&lt;/code&gt;、所属 P 的指针、是否可被抢占等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;M（Machine）&lt;/strong&gt;：真实的 OS 线程，由内核调度。M 负责真正执行 G 的机器码。创建 M 要付出系统调用成本（约 1MB 内核栈 + 内核结构，线程栈），远贵于创建 G。M 通常不超过几千个，且&lt;strong&gt;有上限&lt;/strong&gt;（受系统资源约束，默认 &lt;code&gt;maxmcount=10000&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P（Processor）&lt;/strong&gt;：你可以把它理解成&amp;quot;工位/许可令牌&amp;quot;。P 里有&lt;strong&gt;本地可运行队列 runq&lt;/strong&gt;（长度 256）。G 想被调度运行，必须先被放进某个 P 的 runq，然后 P 绑定到某个 M 上执行队列里的 G。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P 的数量 = &lt;code&gt;GOMAXPROCS&lt;/code&gt;&lt;/strong&gt;（默认取 CPU 逻辑核数），它决定了&lt;strong&gt;同一时刻真正并行执行的 goroutine 上限&lt;/strong&gt;。P 多了，并行度就高；P = 1 时行为接近单线程。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;C++ 对照&lt;/strong&gt;：M ≈ 一个真正运行在 CPU 上的线程；P ≈ 每个线程手头那个任务队列；G ≈ 任务队列里的任务项。你写线程池时是&amp;quot;一个线程，抢全局任务队列&amp;quot;，Go 优化成&amp;quot;每线程一队列 + 偷取&amp;quot;，减少锁竞争。&lt;/p&gt;</description></item><item><title>go mod 依赖管理</title><link>https://www.sylgalaxy.xyz/posts/go-04-01-go-mod/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-01-go-mod/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 CMake+Conan/vcpkg 到 Go modules：官方集成、语义化版本与可复现构建&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 自 1.11 起引入 &lt;strong&gt;Go modules&lt;/strong&gt;（常称 &lt;code&gt;go mod&lt;/code&gt;）作为官方依赖管理工具，1.16 起默认启用。它把「依赖管理」内置到工具链里，一个 &lt;code&gt;go.mod&lt;/code&gt; 文件声明模块与依赖，&lt;code&gt;go.sum&lt;/code&gt; 锁定依赖的校验和，配合**语义化版本（v1.2.3）**和 &lt;code&gt;GOPROXY&lt;/code&gt; 代理，实现可复现构建。&lt;/p&gt;
&lt;p&gt;对于 C++ 开发者，可以把它理解为「&lt;strong&gt;CMake + Conan/vcpkg + 包清单 + 锁文件&lt;/strong&gt;的四合一」：&lt;code&gt;go.mod&lt;/code&gt; ≈ &lt;code&gt;CMakeLists.txt&lt;/code&gt; + &lt;code&gt;conanfile.txt&lt;/code&gt;，&lt;code&gt;go.sum&lt;/code&gt; ≈ 锁文件，&lt;code&gt;go get&lt;/code&gt; ≈ &lt;code&gt;conan install&lt;/code&gt;，&lt;code&gt;replace&lt;/code&gt; 指令 ≈ CMake 的本地路径引入。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go modules 不是「又一个包管理器」，而是&lt;strong&gt;语言官方、零配置文件&lt;/strong&gt;的依赖解决方案。理解 &lt;code&gt;go.mod&lt;/code&gt; 的四个指令（&lt;code&gt;module&lt;/code&gt; / &lt;code&gt;go&lt;/code&gt; / &lt;code&gt;require&lt;/code&gt; / &lt;code&gt;replace&lt;/code&gt;）就掌握了 90% 的日常操作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;CMake / Makefile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go build&lt;/code&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;code&gt;conanfile.txt&lt;/code&gt; / &lt;code&gt;vcpkg.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go.mod&lt;/code&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;code&gt;conan install&lt;/code&gt; / &lt;code&gt;vcpkg install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go get&lt;/code&gt; / &lt;code&gt;go mod tidy&lt;/code&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;Conan &lt;code&gt;conan.lock&lt;/code&gt;（可选）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go.sum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;默认生成&lt;/strong&gt;，锁定每行依赖版本+校验和&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;本地路径依赖&lt;/td&gt;
&lt;td&gt;&lt;code&gt;target_link_libraries&lt;/code&gt; 指向源码目录&lt;/td&gt;
&lt;td&gt;&lt;code&gt;replace ... =&amp;gt; ../xxx&lt;/code&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;Conan &lt;code&gt;[requires] pkg/1.2.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;v1.2.3&lt;/code&gt;（标签含 &lt;code&gt;v&lt;/code&gt; 前缀）&lt;/td&gt;
&lt;td&gt;Go 的版本就是 git tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;代理/镜像&lt;/td&gt;
&lt;td&gt;自建 Artifactory / Nexus&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOPROXY&lt;/code&gt;（如 goproxy.cn）&lt;/td&gt;
&lt;td&gt;环境变量即可切换，无需配置仓库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;私有仓库&lt;/td&gt;
&lt;td&gt;CMake &lt;code&gt;FetchContent&lt;/code&gt; + SSH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOPRIVATE&lt;/code&gt; + git&lt;/td&gt;
&lt;td&gt;绕过代理直连&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;缓存目录&lt;/td&gt;
&lt;td&gt;Conan 本地 cache&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$GOPATH/pkg/mod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;全局共享，只读&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vendor 机制&lt;/td&gt;
&lt;td&gt;把第三方源码拷进仓库&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go mod vendor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可选但常用，利于离线构建&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-module-与-gomod-三大字段"&gt;3.1 module 与 go.mod 三大字段&lt;/h3&gt;
&lt;p&gt;在项目根目录运行 &lt;code&gt;go mod init&lt;/code&gt; 生成 &lt;code&gt;go.mod&lt;/code&gt;：&lt;/p&gt;</description></item><item><title>Go 内存模型：happens-before</title><link>https://www.sylgalaxy.xyz/posts/go-06-04-go-happens-before/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-06-04-go-happens-before/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 有 &lt;code&gt;std::atomic&lt;/code&gt; + 内存序（memory_order），Go 有更少的口子但边界更清楚——channel / Mutex / Once / atomic 各自建立 happens-before&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;变量加了锁就不会有竞态&amp;quot;这种直觉在并发世界里是危险的。真正需要回答的问题是：&lt;strong&gt;goroutine A 写了一个值，goroutine B 什么时候能确定读到它？&lt;/strong&gt; Go 用一份官方文档——&lt;strong&gt;The Go Memory Model&lt;/strong&gt;——精确规定了这些&amp;quot;什么时候&amp;rdquo;。它定义了 &lt;strong&gt;happens-before&lt;/strong&gt; 关系：同步原语（channel、Mutex、WaitGroup、Once、atomic）在&lt;strong&gt;收发/加解锁/等待/原子操作&lt;/strong&gt;之间建立序，从而保证内存可见性。理解它，你才知道为什么&amp;quot;不加同步 flag 读 bool&amp;quot;可能读到旧值，也才知道怎么写出不靠运气的并发程序。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;strong&gt;happens-before（HB）是&amp;quot;一个事件必须在另一个事件之前发生且其结果可见&amp;quot;的形式化保证&lt;/strong&gt;。Go 的并发正确性全部建立在&amp;quot;你用了某个同步原语，它就给你对应的一条 HB 边&amp;quot;上。不用原语 = 没有边 = 编译器/硬件随便重排。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;[memory_order]&lt;/code&gt; 标准章节&lt;/td&gt;
&lt;td&gt;The Go Memory Model（官方文档）&lt;/td&gt;
&lt;td&gt;C++ 需要你精确选 memory_order；Go 不给选项，只规定用了哪个同步原语获得哪条 HB 边&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;互斥锁&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::mutex&lt;/code&gt; 加锁/解锁&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sync.Mutex&lt;/code&gt; Lock/Unlock&lt;/td&gt;
&lt;td&gt;C++ 还要额外配 &lt;code&gt;atomic&lt;/code&gt; 才能安全读共享变量；Go 锁内一切可见&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;code&gt;memory_order_relaxed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;无对应概念&lt;/td&gt;
&lt;td&gt;Go 只有两档：同步原语→对应 HB 保证，非同步→无保证&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原子操作&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::atomic&amp;lt;T&amp;gt;&lt;/code&gt;（load/store/fetch等）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sync/atomic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 1.19 之前 atomic 只防撕裂不建 HB；1.19+ 视作同步点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;初始化一次&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::once_flag&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sync.Once&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;once.Do&lt;/code&gt; 完成后，所有 &lt;code&gt;Do&lt;/code&gt; 返回点看到其写入&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;线程等待&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::thread::join&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sync.WaitGroup.Wait&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Wait&lt;/code&gt; 返回后看到各 &lt;code&gt;Done&lt;/code&gt; 的写入&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;通信同步&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mutex&lt;/code&gt;+&lt;code&gt;cv&lt;/code&gt; 手写&lt;/td&gt;
&lt;td&gt;channel&lt;/td&gt;
&lt;td&gt;收发建立 HB，官方推荐优先 channel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;主动读屏障&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic_thread_fence&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;无直接对应&lt;/td&gt;
&lt;td&gt;Go 用 &lt;code&gt;atomic.Load&lt;/code&gt;/互斥代替 fence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;悬而未决的&amp;quot;下次可见&amp;quot;&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;&amp;ldquo;稍后某个时刻可见&amp;quot;是合法但&lt;strong&gt;无保证&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;这是最常见的 bug 来源&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据竞争检测&lt;/td&gt;
&lt;td&gt;TSan（第三方）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go test -race&lt;/code&gt; 内建&lt;/td&gt;
&lt;td&gt;干干净净的&amp;quot;竞态即报&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-你已经在-c-里见过的序"&gt;3.1 你已经在 C++ 里见过的&amp;quot;序&amp;quot;&lt;/h3&gt;
&lt;p&gt;C++ 的 &lt;code&gt;memory_order&lt;/code&gt; 有三种强度：&lt;code&gt;relaxed&lt;/code&gt;（无序）、&lt;code&gt;acquire/release&lt;/code&gt;（只保证可见但不能越过）、&lt;code&gt;seq_cst&lt;/code&gt;（全局一致）。Go 的模型把选择收敛成一条规则：&lt;/p&gt;</description></item><item><title>Go 语言学习路线（C++ 开发者视角）</title><link>https://www.sylgalaxy.xyz/posts/go-roadmap/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-roadmap/</guid><description>&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#1-%E5%AD%A6%E4%B9%A0%E5%AE%9A%E4%BD%8D%E4%B8%8E%E7%9B%AE%E6%A0%87"&gt;1. 学习定位与目标&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#2-%E4%BB%8E-c-%E5%88%B0-go-%E7%9A%84%E6%80%9D%E7%BB%B4%E8%BD%AC%E6%8D%A2"&gt;2. 从 C++ 到 Go 的思维转换&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#3-%E9%98%B6%E6%AE%B5%E4%B8%80%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E7%AC%AC-12-%E5%91%A8"&gt;3. 阶段一：基础语法（第 1~2 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#4-%E9%98%B6%E6%AE%B5%E4%BA%8C%E8%AF%AD%E8%A8%80%E8%BF%9B%E9%98%B6%E7%AC%AC-34-%E5%91%A8"&gt;4. 阶段二：语言进阶（第 3~4 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#5-%E9%98%B6%E6%AE%B5%E4%B8%89%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E7%AC%AC-56-%E5%91%A8"&gt;5. 阶段三：并发编程（第 5~6 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#6-%E9%98%B6%E6%AE%B5%E5%9B%9B%E5%B7%A5%E7%A8%8B%E5%8C%96%E4%B8%8E%E5%B7%A5%E5%85%B7%E9%93%BE%E7%AC%AC-78-%E5%91%A8"&gt;6. 阶段四：工程化与工具链（第 7~8 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#7-%E9%98%B6%E6%AE%B5%E4%BA%94%E5%AE%9E%E6%88%98%E9%A1%B9%E7%9B%AE"&gt;7. 阶段五：实战项目&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#8-%E9%98%B6%E6%AE%B5%E5%85%AD%E6%B7%B1%E5%85%A5%E5%86%85%E5%B9%95%E8%BF%9B%E9%98%B6"&gt;8. 阶段六：深入内幕（进阶）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#9-%E6%8E%A8%E8%8D%90%E8%B5%84%E6%BA%90"&gt;9. 推荐资源&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#10-%E6%80%BB%E7%BB%93"&gt;10. 总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="1-学习定位与目标"&gt;1. 学习定位与目标&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go 是&lt;strong&gt;为并发与工程效率而生&lt;/strong&gt;的语言。它不是 C++ 的替代品，而是面向&lt;strong&gt;网络服务、云原生、分布式系统&lt;/strong&gt;场景的现代选择。有 C++ 基础意味着你已经懂内存、指针、编译原理、并发难点——这些沉淀可以让你学 Go 的速度远超零基础者。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="11-为什么学-go"&gt;1.1 为什么学 Go&lt;/h3&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;/td&gt;
&lt;td&gt;没有类继承、泛型魔法（1.18 才加）、运算符重载，几小时能读完语法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;编译快&lt;/td&gt;
&lt;td&gt;没有模板实例化与复杂的 ODR，编译速度接近 C 语言&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;并发内建&lt;/td&gt;
&lt;td&gt;goroutine + channel 是语言级能力，不是库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&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;网络、JSON、加密、压缩开箱即用，生态围绕服务端&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;工具链统一&lt;/td&gt;
&lt;td&gt;官方格式化、测试、文档、依赖管理一条龙&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="12-对-c-开发者go-最大的爽点"&gt;1.2 对 C++ 开发者，Go 最大的&amp;quot;爽点&amp;quot;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;没有内存泄漏焦虑&lt;/strong&gt;：GC 自动回收，专注业务逻辑。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;没有头文件割裂&lt;/strong&gt;：一个 &lt;code&gt;.go&lt;/code&gt; 文件即一个单元，&lt;code&gt;import&lt;/code&gt; 即用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;没有 build 时间长&lt;/strong&gt;：秒级编译。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;没有模板错误地狱&lt;/strong&gt;：泛型报错可读性好得多。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="2-从-c-到-go-的思维转换"&gt;2. 从 C++ 到 Go 的思维转换&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：这一节是全篇最关键的部分。C++ 功底在 Go 里&lt;strong&gt;既是资产也是包袱&lt;/strong&gt;——资产是并发、内存模型、数据结构的直觉；包袱是&amp;quot;继承 + 异常 + 手动内存&amp;quot;的思维定式，需要刻意转换。&lt;/p&gt;</description></item><item><title>goroutine</title><link>https://www.sylgalaxy.xyz/posts/go-03-01-goroutine/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-01-goroutine/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 并发的基本执行单元：比线程轻量十倍的绿色协程，由 Go 运行时调度&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一c-对照速查表"&gt;一、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::thread&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go func()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;goroutine 由运行时管理，不映射到 OS 线程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;创建成本&lt;/td&gt;
&lt;td&gt;~1MB 栈 + 系统调用&lt;/td&gt;
&lt;td&gt;~2KB 栈，动态增长&lt;/td&gt;
&lt;td&gt;goroutine 创建成本极低，可轻松创建上万&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;启动方式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::thread t(func); t.join();&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go func()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 无需手动 join，用 channel/WaitGroup 同步&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;调度模型&lt;/td&gt;
&lt;td&gt;1:1 映射 OS 线程&lt;/td&gt;
&lt;td&gt;M:N 调度（GMP 模型）&lt;/td&gt;
&lt;td&gt;运行时把 N 个 goroutine 调度到 M 个线程上&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;栈大小&lt;/td&gt;
&lt;td&gt;固定（通常 1~8MB）&lt;/td&gt;
&lt;td&gt;初始 2KB，按需增长/收缩&lt;/td&gt;
&lt;td&gt;同一地址空间下可容纳海量 goroutine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;终止方式&lt;/td&gt;
&lt;td&gt;thread 析构或 detach&lt;/td&gt;
&lt;td&gt;主 goroutine 结束则全部退出&lt;/td&gt;
&lt;td&gt;goroutine 是 &amp;ldquo;fire and forget&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：goroutine 是 Go 并发的基石。创建一个 goroutine 只用一个 &lt;code&gt;go&lt;/code&gt; 关键字，运行时自动处理调度、栈管理和线程复用。但 goroutine 之间需要通过 &lt;strong&gt;channel&lt;/strong&gt; 或 &lt;strong&gt;sync 包&lt;/strong&gt; 同步，否则会出现数据竞争。&lt;/p&gt;</description></item><item><title>Map（哈希表）</title><link>https://www.sylgalaxy.xyz/posts/go-01-05-map/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-05-map/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的内置关联容器，键值对存储，底层是哈希表&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一概述"&gt;一、概述&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;map&lt;/code&gt; 是 Go 的内置数据结构，用于存储键值对。它等价于 C++ 的 &lt;code&gt;std::unordered_map&lt;/code&gt;——基于哈希表实现，&lt;strong&gt;不是&lt;/strong&gt;红黑树（Go 没有 &lt;code&gt;std::map&lt;/code&gt; 那样的有序容器）。&lt;/p&gt;
&lt;p&gt;核心特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引用类型，赋值和传参共享底层数组&lt;/li&gt;
&lt;li&gt;键必须支持 &lt;code&gt;==&lt;/code&gt; 比较（可哈希）&lt;/li&gt;
&lt;li&gt;遍历顺序不确定（哈希表特性）&lt;/li&gt;
&lt;li&gt;并发读写会触发 &lt;strong&gt;fatal&lt;/strong&gt;（不是 data race，直接崩程序）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;C++&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;map[K]V&lt;/code&gt; 类型声明&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::unordered_map&amp;lt;K,V&amp;gt;&lt;/code&gt; 类型声明&lt;/td&gt;
&lt;td&gt;声明一个 map 类型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m := map[string]int{}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto m = unordered_map&amp;lt;string,int&amp;gt;();&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字面量初始化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m := make(map[string]int)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto m = unordered_map&amp;lt;string,int&amp;gt;();&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;make 初始化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m := make(map[string]int, 64)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto m = unordered_map&amp;lt;string,int&amp;gt;(64);&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;预分配容量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m[&amp;quot;key&amp;quot;] = 42&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m[&amp;quot;key&amp;quot;] = 42;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;插入/修改&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;delete(m, &amp;quot;key&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m.erase(&amp;quot;key&amp;quot;);&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;删除键&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;val, ok := m[&amp;quot;key&amp;quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto it = m.find(&amp;quot;key&amp;quot;); it != m.end()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;查找（双返回值）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;len(m)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m.size()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;获取大小&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nil map&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nullptr&lt;/code&gt; 的 map&lt;/td&gt;
&lt;td&gt;未初始化的 map&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for k, v := range m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for (auto&amp;amp; [k, v] : m)&lt;/code&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;code&gt;std::map&amp;lt;K,V&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 没有有序 map&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三声明与初始化"&gt;三、声明与初始化&lt;/h2&gt;
&lt;h3 id="31-字面量初始化最常用"&gt;3.1 字面量初始化（最常用）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 字面量初始化：声明 + 赋值一步到位&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ages&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Bob&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Carol&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ages&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// map[Alice:30 Bob:25 Carol:28]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 空 map&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;empty&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(len(&lt;span style="color:#a6e22e"&gt;empty&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-make-初始化"&gt;3.2 make 初始化&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// make 创建空 map，可选预分配容量（提高性能）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;scores&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 零值容量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;scores2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 预分配 64 个槽位&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 适用场景：已知大致大小，预分配可减少扩容次数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;users&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="33-nil-map未初始化"&gt;3.3 nil map（未初始化）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#75715e"&gt;// nil map，值为 nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// map[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(len(&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 0 — len 对 nil map 返回 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="34-c-对照"&gt;3.4 C++ 对照&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ages := map[string]int{&amp;quot;Alice&amp;quot;: 30}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto ages = unordered_map&amp;lt;string,int&amp;gt;{{&amp;quot;Alice&amp;quot;, 30}};&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m := make(map[string]int)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto m = unordered_map&amp;lt;string,int&amp;gt;();&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m := make(map[string]int, 64)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto m = unordered_map&amp;lt;string,int&amp;gt;(64);&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;var m map[string]int&lt;/code&gt; (nil)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unordered_map&amp;lt;string,int&amp;gt;* m = nullptr;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="四增删改查"&gt;四、增删改查&lt;/h2&gt;
&lt;h3 id="41-增--改赋值"&gt;4.1 增 / 改（赋值）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 不存在的 key → 插入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;apple&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;banana&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 已存在的 key → 修改&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;apple&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// map[apple:10 banana:3]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="42-查双返回值-ok-模式"&gt;4.2 查（双返回值 ok 模式）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;y&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 双返回值：值 + 是否存在（ok 模式）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;val&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;val&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 1 true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;val2&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;z&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;val2&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok2&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 0 false（零值，不存在）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// C++ 对比：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// auto it = m.find(&amp;#34;x&amp;#34;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// if (it != m.end()) { /* 找到 */ }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;为什么需要 ok 模式？&lt;/strong&gt; 如果值类型是 &lt;code&gt;int&lt;/code&gt;，零值是 &lt;code&gt;0&lt;/code&gt;，无法区分&amp;quot;值为 0&amp;quot;和&amp;quot;不存在&amp;quot;。&lt;code&gt;ok&lt;/code&gt; 布尔值解决了这个问题。&lt;/p&gt;</description></item><item><title>OpenCV 4.10 + Visual Studio 环境配置：属性页手动配法</title><link>https://www.sylgalaxy.xyz/posts/opencv-vs-env-setup/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/opencv-vs-env-setup/</guid><description>&lt;p&gt;在 Visual Studio 项目里用属性页手动配置 OpenCV 4.10 的完整步骤：包含目录、库目录、链接器输入、环境变量，四步配好后用一段自检代码验证。（如果用 CMake 工程，则改为环境变量 + &lt;code&gt;find_package&lt;/code&gt; 的方案，不用逐项目配属性页。）&lt;/p&gt;
&lt;h2 id="一配置步骤"&gt;一、配置步骤&lt;/h2&gt;
&lt;h3 id="1-包含目录"&gt;1. 包含目录&lt;/h3&gt;
&lt;p&gt;项目属性 → VC++ 目录 → 包含目录，添加：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\include
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-库目录"&gt;2. 库目录&lt;/h3&gt;
&lt;p&gt;项目属性 → VC++ 目录 → 库目录，添加：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\lib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;vc16 对应 Visual Studio 2019/2022&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="3-链接器输入"&gt;3. 链接器输入&lt;/h3&gt;
&lt;p&gt;项目属性 → 链接器 → 输入 → 附加依赖项，添加：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;opencv_world4100.lib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-环境变量"&gt;4. 环境变量&lt;/h3&gt;
&lt;p&gt;系统环境变量 Path 中添加：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\bin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="二验证"&gt;二、验证&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;opencv2/opencv.hpp&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;cout &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;OpenCV Version: &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; CV_VERSION &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三常见问题"&gt;三、常见问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;运行时弹出找不到 dll → 检查环境变量是否配置正确&lt;/li&gt;
&lt;li&gt;链接错误 → 检查库目录和附加依赖项&lt;/li&gt;
&lt;li&gt;Release / Debug 库混用 → Debug 构建须链接带 &lt;code&gt;d&lt;/code&gt; 后缀的 &lt;code&gt;opencv_world4100d.lib&lt;/code&gt;，Release 用 &lt;code&gt;opencv_world4100.lib&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OpenCV 常用 API：图像读写、显示与颜色空间转换</title><link>https://www.sylgalaxy.xyz/posts/opencv-common-api/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/opencv-common-api/</guid><description>&lt;p&gt;OpenCV 入门最常用的几组 API：图像读取、显示、颜色空间转换、保存、获取图像信息。&lt;/p&gt;
&lt;h2 id="一图像读取与显示"&gt;一、图像读取与显示&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;opencv2/opencv.hpp&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; cv;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 读取图像
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Mat img &lt;span style="color:#f92672"&gt;=&lt;/span&gt; imread(&lt;span style="color:#e6db74"&gt;&amp;#34;test.jpg&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 显示图像
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; imshow(&lt;span style="color:#e6db74"&gt;&amp;#34;窗口名&amp;#34;&lt;/span&gt;, img);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 等待按键
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; waitKey(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="二灰度图转换"&gt;二、灰度图转换&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mat gray;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cvtColor(img, gray, COLOR_BGR2GRAY);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;imshow(&lt;span style="color:#e6db74"&gt;&amp;#34;灰度图&amp;#34;&lt;/span&gt;, gray);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三hsv-图像转换"&gt;三、HSV 图像转换&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mat hsv;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cvtColor(img, hsv, COLOR_BGR2HSV);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;imshow(&lt;span style="color:#e6db74"&gt;&amp;#34;HSV&amp;#34;&lt;/span&gt;, hsv);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="四常用颜色空间"&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;BGR → 灰度&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COLOR_BGR2GRAY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BGR → HSV&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COLOR_BGR2HSV&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BGR → RGB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COLOR_BGR2RGB&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;灰度 → BGR&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COLOR_GRAY2BGR&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="五图像保存"&gt;五、图像保存&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;imwrite(&lt;span style="color:#e6db74"&gt;&amp;#34;output.jpg&amp;#34;&lt;/span&gt;, gray);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="六获取图像信息"&gt;六、获取图像信息&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; width &lt;span style="color:#f92672"&gt;=&lt;/span&gt; img.cols; &lt;span style="color:#75715e"&gt;// 宽度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; height &lt;span style="color:#f92672"&gt;=&lt;/span&gt; img.rows; &lt;span style="color:#75715e"&gt;// 高度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; channels &lt;span style="color:#f92672"&gt;=&lt;/span&gt; img.channels(); &lt;span style="color:#75715e"&gt;// 通道数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>OpenCV 像素遍历：at&lt;&gt; 与 ptr&lt;&gt; 两种方式对比</title><link>https://www.sylgalaxy.xyz/posts/opencv-pixel-traversal/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/opencv-pixel-traversal/</guid><description>&lt;p&gt;OpenCV 访问像素的两种方式：&lt;code&gt;at&amp;lt;&amp;gt;&lt;/code&gt; 直接访问和 &lt;code&gt;ptr&amp;lt;&amp;gt;&lt;/code&gt; 指针访问。&lt;/p&gt;
&lt;h2 id="一方式一at-直接访问"&gt;一、方式一：at&amp;lt;&amp;gt; 直接访问&lt;/h2&gt;
&lt;p&gt;通过行列索引直接访问像素，代码简洁但每次访问都有边界检查开销。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 单通道（灰度图）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uchar pixel &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.at&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;uchar&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(i, j);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;image.at&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;uchar&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(i, j) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; pixel;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 三通道（彩色图）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Vec3b pixel &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.at&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;Vec3b&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(i, j);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixel[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; pixel[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]; &lt;span style="color:#75715e"&gt;// B
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixel[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; pixel[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]; &lt;span style="color:#75715e"&gt;// G
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixel[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; pixel[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]; &lt;span style="color:#75715e"&gt;// R
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;image.at&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;Vec3b&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(i, j) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pixel;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="二方式二ptr-指针访问"&gt;二、方式二：ptr&amp;lt;&amp;gt; 指针访问&lt;/h2&gt;
&lt;p&gt;获取行首指针后直接偏移，性能更优（无边界检查）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 单通道
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uchar&lt;span style="color:#f92672"&gt;*&lt;/span&gt; rowPtr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.ptr&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;uchar&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rowPtr[j] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; rowPtr[j];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 三通道
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Vec3b&lt;span style="color:#f92672"&gt;*&lt;/span&gt; rowPtr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.ptr&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;Vec3b&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Vec3b pixel &lt;span style="color:#f92672"&gt;=&lt;/span&gt; rowPtr[j];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixel[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; pixel[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixel[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; pixel[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pixel[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; pixel[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rowPtr[j] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; pixel;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三对比"&gt;三、对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;at&amp;lt;&amp;gt;&lt;/th&gt;
&lt;th&gt;ptr&amp;lt;&amp;gt;&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;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="四反转图像示例完整"&gt;四、反转图像示例（完整）&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;invertImage&lt;/span&gt;(Mat&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; image) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; w &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.cols;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.rows;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; channels &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.channels();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; i &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; h; i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; uchar&lt;span style="color:#f92672"&gt;*&lt;/span&gt; rowPtr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; image.ptr&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;uchar&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; j &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; j &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; w &lt;span style="color:#f92672"&gt;*&lt;/span&gt; channels; j&lt;span style="color:#f92672"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rowPtr[j] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; rowPtr[j];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; imshow(&lt;span style="color:#e6db74"&gt;&amp;#34;Inverted&amp;#34;&lt;/span&gt;, image);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可用 &lt;code&gt;rowPtr[j] = 255 - rowPtr[j]&lt;/code&gt; 一次处理所有通道，无需区分通道数。&lt;/p&gt;</description></item><item><title>pprof 性能调优</title><link>https://www.sylgalaxy.xyz/posts/go-06-05-pprof/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-06-05-pprof/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 里要弄 4~5 套工具（perf / valgrind / gprof / TSan）；Go 把 CPU、内存、goroutine、锁的剖面图都装进了一个 &lt;code&gt;pprof&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;性能调优第一步永远不是&amp;quot;猜&amp;quot;，是&amp;quot;量&amp;quot;。Go 的 &lt;strong&gt;pprof&lt;/strong&gt;（profile）机制提供一套统一的剖析框架：CPU、堆内存、分配、goroutine、锁竞争、阻塞延时的剖面数据，既能离线抓（&lt;code&gt;runtime/pprof&lt;/code&gt;、&lt;code&gt;go test -cpuprofile&lt;/code&gt;），也能在线实时抓（&lt;code&gt;net/http/pprof&lt;/code&gt;）。配合 &lt;code&gt;go tool pprof&lt;/code&gt; 的 &lt;code&gt;top / list / peek / web&lt;/code&gt; 交互和火焰图，你能在几分钟内定位 CPU 热点、内存黑洞、goroutine 泄漏。对用惯 &lt;code&gt;perf&lt;/code&gt;/&lt;code&gt;valgrind&lt;/code&gt;/&lt;code&gt;gprof&lt;/code&gt; 的 C++ 开发者来说，这是一次&amp;quot;多工具合一&amp;quot;的升级。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：pprof 是&lt;strong&gt;采样式剖析&lt;/strong&gt;：按频率打断程序，记录当时正在执行的函数调用栈，最后统计&amp;quot;每个函数在多少样本里出现&amp;quot;。&lt;strong&gt;flat&lt;/strong&gt; 是&amp;quot;函数自己耗的&amp;quot;，&lt;strong&gt;cum&lt;/strong&gt; 是&amp;quot;含它调用的所有子函数&amp;quot;——读懂这两个数字是使用 pprof 的核心。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU 剖析&lt;/td&gt;
&lt;td&gt;&lt;code&gt;perf record/report&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;runtime/pprof&lt;/code&gt; + &lt;code&gt;cpu.prof&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 内置采样器，无需 perf_event 权限&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;堆内存剖析&lt;/td&gt;
&lt;td&gt;&lt;code&gt;valgrind --tool=massif&lt;/code&gt; / &lt;code&gt;heaptrack&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;memprofile&lt;/code&gt; + heap view&lt;/td&gt;
&lt;td&gt;pprof 同时给 inuse/alloc 两维度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;线级热点&lt;/td&gt;
&lt;td&gt;&lt;code&gt;perf annotate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go tool pprof -list&lt;/code&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;code&gt;perf script&lt;/code&gt; + 第三方 FlameGraph&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go tool pprof -http&lt;/code&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;code&gt;helgrind&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;mutex/block profile&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;code&gt;gprof&lt;/code&gt;（编译期插桩）&lt;/td&gt;
&lt;td&gt;pprof 自动采样&lt;/td&gt;
&lt;td&gt;Go 无插桩成本，直接采样&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;内存泄漏排查&lt;/td&gt;
&lt;td&gt;&lt;code&gt;valgrind --leak-check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;goroutine profile + &lt;code&gt;alloc_objects&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 看&amp;quot;分配来源&amp;quot;而非&amp;quot;泄漏点&amp;quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;运行中抓取&lt;/td&gt;
&lt;td&gt;需 &lt;code&gt;perf&lt;/code&gt; 权限/SAMPLING&lt;/td&gt;
&lt;td&gt;&lt;code&gt;net/http/pprof&lt;/code&gt; 一键开&lt;/td&gt;
&lt;td&gt;线上服务开端口即可&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-profile-是什么采样式剖析"&gt;3.1 profile 是什么：采样式剖析&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;时间轴 ──────────────────────────────────────────►
采样点：每隔 t（如 100 次/秒 = 10ms）触发 SIGPROF
每次记录：当前 goroutine 的完整调用栈（PC → 函数名）
┌────┐┌────┐┌────┐┌────┐
│foo ││bar ││foo ││baz │ 每个采样点保留栈帧
│ main││ foo││ main││ foo │ 最后统计: foo 出现 3/4 次
└────┘└────┘└────┘└────┘
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CPU profile&lt;/strong&gt;：默认每 10ms（100Hz）采样一次正在执行的 G 的栈。&lt;strong&gt;只有&amp;quot;在 CPU 上运行&amp;quot;的 G 会被采到&lt;/strong&gt;——所以纯 IO/阻塞的 goroutine 在 CPU profile 里很低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;heap profile&lt;/strong&gt;：不是采样，是&lt;strong&gt;快照&lt;/strong&gt;。记录&amp;quot;当前存活对象&amp;quot;的分配点（用于看内存滞留）或&amp;quot;累计分配&amp;quot;（&lt;code&gt;-alloc_space&lt;/code&gt;/&lt;code&gt;-alloc_objects&lt;/code&gt;，用于看分配大山）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;goroutine profile&lt;/strong&gt;：每个 goroutine 当前栈（含状态），看泄漏。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mutex/block profile&lt;/strong&gt;：记录锁等待与阻塞事件（需要 &lt;code&gt;runtime.SetBlockProfileRate&lt;/code&gt; / &lt;code&gt;SetMutexProfileFraction&lt;/code&gt; 开启）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="32-离线抓取runtimepprof-与-go-test--profile"&gt;3.2 离线抓取：&lt;code&gt;runtime/pprof&lt;/code&gt; 与 &lt;code&gt;go test -profile&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;方式一：&lt;code&gt;go test&lt;/code&gt; 直接出谱（最常用）&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>QMovie 动画播放</title><link>https://www.sylgalaxy.xyz/posts/qt-qmovie/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-qmovie/</guid><description>&lt;p&gt;&lt;code&gt;QMovie&lt;/code&gt; 是 Qt 中用于播放动画（主要是 &lt;code&gt;GIF&lt;/code&gt; 格式）的类。它本身不是一个控件，不能直接显示在界面上，通常需要借助 &lt;code&gt;QLabel&lt;/code&gt;（或 &lt;code&gt;QGraphicsView&lt;/code&gt;）来展示播放效果。&lt;/p&gt;
&lt;p&gt;它的核心作用是：逐帧读取动图文件，按时间间隔把每一帧渲染出来，从而实现动画播放。&lt;/p&gt;
&lt;h1 id="1-效果演示"&gt;1. 效果演示&lt;/h1&gt;
&lt;p&gt;通过 &lt;code&gt;QLabel&lt;/code&gt; 显示一个加载中的 GIF 动画，并提供「开始 / 暂停 / 停止」三个按钮，演示 &lt;code&gt;QMovie&lt;/code&gt; 的常用接口。&lt;/p&gt;
&lt;h1 id="2-属性和方法"&gt;2. 属性和方法&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;QMovie&lt;/code&gt; 的工作流程大致是：&lt;code&gt;加载文件 → 启动播放 → 播放结束&lt;/code&gt;。常用的属性和方法如下。&lt;/p&gt;
&lt;h2 id="21-构造与加载"&gt;2.1 构造与加载&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 通过文件名构造
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QMovie(&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; QString &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;fileName, &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; QByteArray &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;format &lt;span style="color:#f92672"&gt;=&lt;/span&gt; QByteArray(), QObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;parent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 通过 QIODevice 构造（可用于资源文件、网络数据等）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QMovie(QIODevice &lt;span style="color:#f92672"&gt;*&lt;/span&gt;device, &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; QByteArray &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;format &lt;span style="color:#f92672"&gt;=&lt;/span&gt; QByteArray(), QObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;parent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 设置 / 获取动画的文件名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setFileName&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; QString &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;fileName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QString &lt;span style="color:#a6e22e"&gt;fileName&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 判断动画是否有效（文件是否能被正确解析）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;isValid&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="22-播放控制"&gt;2.2 播放控制&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 开始播放
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;start&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 暂停 / 继续(QMovie 没有 pause()/resume(),只有这个开关式接口,且它是一个槽)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setPaused&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; paused); &lt;span style="color:#75715e"&gt;// true 为暂停，false 为继续
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 没有 paused()/isPaused() 这样的查询方法，是否暂停用 state() 判断
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MovieState &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// NotRunning / Paused / Running
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 停止播放，并回到第一帧
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stop&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 缓存模式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CacheMode &lt;span style="color:#a6e22e"&gt;cacheMode&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setCacheMode&lt;/span&gt;(CacheMode mode);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;QMovie&lt;/code&gt; 提供的播放控制比较简单，注意 &lt;code&gt;stop()&lt;/code&gt; 与 &lt;code&gt;setPaused(true)&lt;/code&gt; 的区别：&lt;/p&gt;</description></item><item><title>QSlider滑动条</title><link>https://www.sylgalaxy.xyz/posts/qt-qslider/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-qslider/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文搬运转载自 &lt;a href="https://www.qt1024.cn/qt_basic/2_9_QSlider"&gt;明王讲QT - QSlider&lt;/a&gt;，仅供学习记录使用。版权归原作者所有。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="qslider-滑动条控件"&gt;QSlider 滑动条控件&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;QSlider&lt;/code&gt;是滑动条控件
它允许用户通过拖动滑块来选择一个范围内的值。通常用于调整音量、亮度、进度等需要连续数值输入的场景&lt;/p&gt;
&lt;h1 id="1-效果演示三个滑动条分别用来调节rgb三个颜色的值并显示到左侧各自的文本框中"&gt;1. 效果演示三个滑动条，分别用来调节&lt;code&gt;RGB&lt;/code&gt;三个颜色的值，并显示到左侧各自的文本框中&lt;/h1&gt;
&lt;p&gt;并且将&lt;code&gt;RGB&lt;/code&gt;这三个颜色的组合，来设置上面的文本框的背景颜色
&lt;img loading="lazy" src="https://www-qt1024-cn.oss-cn-beijing.aliyuncs.com/slider.gif"&gt;&lt;/p&gt;
&lt;h1 id="2-属性和方法qslider继承自qabstractslider它的绝大多数属性都是从qabstractslider继承而来的"&gt;2. 属性和方法&lt;code&gt;QSlider&lt;/code&gt;继承自&lt;code&gt;QAbstractSlider&lt;/code&gt;，它的绝大多数属性都是从&lt;code&gt;QAbstractSlider&lt;/code&gt;继承而来的。&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;QSlider&lt;/code&gt;有很多属性，完整的可查看帮助文档。这里仅列出常用的属性和方法&lt;/p&gt;
&lt;h2 id="21-值滑动条和值相关的属性包括当前值最大值最小值"&gt;2.1 值滑动条和值相关的属性包括：当前值、最大值、最小值&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取和设置当前值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setValue&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取和设置最大值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;maximum&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setMaximum&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取和设置最小值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;minimum&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setMinimum&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 一次设置最大值和最小值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; setRange(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; min, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; max)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="22-方向qt中滑动条有水平滑动条和垂直滑动条之分通过修改orientation属性来设置"&gt;2.2 方向&lt;code&gt;Qt&lt;/code&gt;中滑动条有水平滑动条和垂直滑动条之分，通过修改&lt;code&gt;orientation&lt;/code&gt;属性来设置&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取和设置滑动条的方向
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Qt&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Orientation orientation() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setOrientation&lt;/span&gt;(Qt&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Orientation);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="23-步长步长是指滑动条一次增加或减少的值这里又包括两个步长"&gt;2.3 步长步长是指滑动条一次增加或减少的值。这里又包括两个步长：&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;singleStep：是指按键盘的左右箭头（←/→）时的步长&lt;/li&gt;
&lt;li&gt;pageStep：是指点击滑块两侧时的步长&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取和设置singleStep
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;singleStep&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setSingleStep&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取和设置pageStep
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pageStep&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setPageStep&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="24-刻度线cpp"&gt;2.4 刻度线```cpp&lt;/h2&gt;
&lt;p&gt;// 获取和设置刻度线间隔
int tickInterval() const
void setTickInterval(int ti)&lt;/p&gt;
&lt;p&gt;// 获取和设置刻度线的位置
QSlider::TickPosition tickPosition() const
void setTickPosition(QSlider::TickPosition position)&lt;/p&gt;</description></item><item><title>Qt Model/View 架构详解 — Item Model 体系</title><link>https://www.sylgalaxy.xyz/posts/qt-qt-modelview-mvc/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-qt-modelview-mvc/</guid><description>&lt;h2 id="一架构总览"&gt;一、架构总览&lt;/h2&gt;
&lt;p&gt;Qt 的 Model/View 架构是对经典 MVC 模式的实现与改造：&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;th&gt;对应类&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model&lt;/strong&gt;（数据源）&lt;/td&gt;
&lt;td&gt;存储数据、提供数据访问接口&lt;/td&gt;
&lt;td&gt;QAbstractItemModel 系列&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;View&lt;/strong&gt;（视图）&lt;/td&gt;
&lt;td&gt;显示数据、处理用户交互&lt;/td&gt;
&lt;td&gt;QTableView, QTreeView, QListView&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Delegate&lt;/strong&gt;（委托）&lt;/td&gt;
&lt;td&gt;自定义渲染和编辑&lt;/td&gt;
&lt;td&gt;QStyledItemDelegate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;核心思想&lt;/strong&gt;：数据（Model）与展示（View）完全解耦，同一个 Model 可以同时被多个 View 显示。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二类继承体系"&gt;二、类继承体系&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;QObject
└── QAbstractItemModel ← 所有 Item Model 的根基类
├── QAbstractListModel ← 简单一维列表的抽象基类
│ └── QStringListModel
├── QAbstractTableModel ← 二维表格的抽象基类(自己写表模型时继承它)
├── QStandardItemModel ← 开箱即用的通用模型（树/表/列表通吃）
└── SQL 模型是三级单链,不是从 QAbstractTableModel 派生:
QAbstractItemModel → QSqlQueryModel → QSqlTableModel → QSqlRelationalTableModel
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;其他直接从 QAbstractItemModel 派生的专用模型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;QFileSystemModel&lt;/strong&gt; — 文件系统树&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="三核心索引系统qmodelindex"&gt;三、核心索引系统：QModelIndex&lt;/h2&gt;
&lt;p&gt;Model/View 的通信枢纽是 &lt;strong&gt;QModelIndex&lt;/strong&gt;（模型索引）。&lt;/p&gt;</description></item><item><title>Qt MVC 与达梦数据库集成</title><link>https://www.sylgalaxy.xyz/posts/db-01-qt-mvc/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/db-01-qt-mvc/</guid><description>&lt;blockquote&gt;
&lt;p&gt;电力设备运维场景：变电站设备经 IEC 104 规约报文上送遥测/遥信数据，Qt 后台接收解析后写入达梦数据库，界面用 Qt Model/View（MVC）框架展示。
数据库部分讲解详细，全程与 MySQL 对比。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一场景背景"&gt;一、场景背景&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;业务链路：&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;变电站设备 --(IEC 104 报文)--&amp;gt; Qt 后台 TCP 服务端 --&amp;gt; 报文解析
--&amp;gt; 达梦数据库(DM8) --&amp;gt; QSqlTableModel --绑定--&amp;gt; QTableView 界面
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;遥测（YC）&lt;/strong&gt;：电流、电压、功率等模拟量，周期上送。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;遥信（YX）&lt;/strong&gt;：开关位置、刀闸状态等开关量，变位上送。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;本篇定位&lt;/strong&gt;：MVC 基础原理（QModelIndex/Role/Delegate 机制）已在
&lt;a href="../Qt/Qt_ModelView_MVC%E6%9E%B6%E6%9E%84%E8%AF%A6%E8%A7%A3.md"&gt;../Qt/Qt_ModelView_MVC架构详解.md&lt;/a&gt; 详细讲解，本篇不重复，
重点放在&lt;strong&gt;数据库侧&lt;/strong&gt;：达梦连接、三种数据库 Model 的用法、报文落库与界面刷新的完整链路。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二达梦连接配置详细"&gt;二、达梦连接配置（详细）&lt;/h2&gt;
&lt;h3 id="21-为什么-qt-用-odbc-连接达梦"&gt;2.1 为什么 Qt 用 ODBC 连接达梦&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;对比项&lt;/th&gt;
&lt;th&gt;达梦 DM8&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Qt 驱动&lt;/td&gt;
&lt;td&gt;无官方原生驱动，走 &lt;strong&gt;ODBC&lt;/strong&gt;（&lt;code&gt;QODBC&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;官方 &lt;code&gt;QMYSQL&lt;/code&gt; 驱动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;端口&lt;/td&gt;
&lt;td&gt;5236&lt;/td&gt;
&lt;td&gt;3306&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;驱动来源&lt;/td&gt;
&lt;td&gt;达梦安装目录自带 ODBC 驱动（&lt;code&gt;drivers/odbc/&lt;/code&gt; 下）&lt;/td&gt;
&lt;td&gt;Qt 编译时编译 qsqlmysql 插件&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;MySQL 有 &lt;code&gt;QMYSQL&lt;/code&gt; 驱动，直接 &lt;code&gt;QSqlDatabase::addDatabase(&amp;quot;QMYSQL&amp;quot;)&lt;/code&gt; 即可。
达梦没有对应的 Qt 原生驱动，只能通过微软 ODBC 或 unixODBC 桥接，Qt 侧统一使用 &lt;code&gt;QODBC&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>Qt 架构阅读方法：从构造函数入手</title><link>https://www.sylgalaxy.xyz/posts/qt-note/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-note/</guid><description>&lt;blockquote&gt;
&lt;p&gt;看 Qt 桌面程序，不要从头文件按顺序&amp;quot;从小往大&amp;quot;看——Qt 没有顺序这一说，要&lt;strong&gt;从主页面构造函数去总结架构&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一核心观点"&gt;一、核心观点&lt;/h2&gt;
&lt;p&gt;Qt 程序（尤其带界面的桌面应用）里，&lt;strong&gt;构造函数是&amp;quot;所有功能的展示&amp;quot;&lt;/strong&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;strong&gt;信号与槽连接&lt;/strong&gt;（最重要）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;想看懂某一个页面的功能大局，步骤是：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;看构造函数 → 看构造函数里的注释 → 找被调用的实现方法
→ 看&amp;#34;哪些被使用了、有什么用&amp;#34; → 再去对应头文件/源文件看定义
→ 看懂
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;而不是：打开一个头文件，从头到尾按声明顺序啃。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二为什么-qt-不能从头文件按顺序看"&gt;二、为什么 Qt 不能&amp;quot;从头文件按顺序看&amp;quot;&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;/td&gt;
&lt;td&gt;头文件只是&lt;strong&gt;声明集合&lt;/strong&gt;，不含调用关系；顺序 ≠ 执行顺序&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;从最小的类看起&lt;/td&gt;
&lt;td&gt;小类之间没有依赖线索，看完全部也不懂&amp;quot;为什么存在&amp;quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;先读业务函数&lt;/td&gt;
&lt;td&gt;不知道它被谁调用、在什么时机触发（信号槽是异步/解耦的）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;想找&amp;quot;程序入口→顺序执行&amp;quot;&lt;/td&gt;
&lt;td&gt;Qt 是&lt;strong&gt;事件驱动&lt;/strong&gt;的，没有线性执行流&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Qt 程序的&amp;quot;执行顺序&amp;quot;不是代码顺序，而是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;main()&lt;/code&gt; 里创建主窗口 → 执行构造函数&lt;/li&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;/ol&gt;
&lt;p&gt;所以&lt;strong&gt;构造函数 = 架构入口&lt;/strong&gt;，是唯一能&amp;quot;一览全局&amp;quot;的地方。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="三构造函数里到底有什么"&gt;三、构造函数里到底有什么&lt;/h2&gt;
&lt;p&gt;以常见主窗口为例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MainWindow&lt;span style="color:#f92672"&gt;::&lt;/span&gt;MainWindow(QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;parent)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; QMainWindow(parent)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 1. 窗口属性初始化
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; setWindowTitle(&lt;span style="color:#e6db74"&gt;&amp;#34;示例程序&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resize(&lt;span style="color:#ae81ff"&gt;800&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 2. 加载函数：资源、配置、数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; loadConfig(); &lt;span style="color:#75715e"&gt;// 读配置文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; initDatabase(); &lt;span style="color:#75715e"&gt;// 连接数据库
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; setupToolbar(); &lt;span style="color:#75715e"&gt;// 加载图标/工具栏
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 3. 功能函数：创建控件与布局
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; createCentralWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; createStatusBar();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; createMenu();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 4. ⭐ 信号与槽连接（核心：把&amp;#34;谁&amp;#34;和&amp;#34;谁&amp;#34;绑起来）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connect(ui&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;startBtn, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QPushButton&lt;span style="color:#f92672"&gt;::&lt;/span&gt;clicked,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;MainWindow&lt;span style="color:#f92672"&gt;::&lt;/span&gt;onStart);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connect(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;MainWindow&lt;span style="color:#f92672"&gt;::&lt;/span&gt;dataReady,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ui&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;table, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;TableWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;refresh);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connect(timer, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QTimer&lt;span style="color:#f92672"&gt;::&lt;/span&gt;timeout,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;MainWindow&lt;span style="color:#f92672"&gt;::&lt;/span&gt;updateStatus);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;构造函数 = &lt;strong&gt;组装说明书&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>Qt 网络编程 01：TCP 客户端与服务端（第一天）</title><link>https://www.sylgalaxy.xyz/posts/qt-qt-tcp/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-qt-tcp/</guid><description>&lt;blockquote&gt;
&lt;p&gt;适用版本：Qt 6.9 / MinGW / C++17
更新日期：2026-08-19
源码位置：&lt;code&gt;&amp;lt;你的工程目录&amp;gt;\net&lt;/code&gt;（TcpSocket / Tcpserver / TCP_Client / TCP_Server 四个项目）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E4%B8%80%E4%BB%8A%E5%A4%A9%E5%81%9A%E4%BA%86%E4%BB%80%E4%B9%88"&gt;一、今天做了什么&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E4%BA%8C%E9%A1%B9%E7%9B%AE%E6%B8%85%E5%8D%95%E4%B8%8E%E8%A7%92%E8%89%B2%E5%88%86%E5%B7%A5"&gt;二、项目清单与角色分工&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E4%B8%89%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9Cpro-%E5%8A%A0-network-%E6%A8%A1%E5%9D%97"&gt;三、准备工作：.pro 加 network 模块&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%9B%9B%E6%8E%A7%E5%88%B6%E5%8F%B0%E7%89%88%E5%AE%A2%E6%88%B7%E7%AB%AF-tcpsocket"&gt;四、控制台版：客户端 TcpSocket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E4%BA%94%E6%8E%A7%E5%88%B6%E5%8F%B0%E7%89%88%E6%9C%8D%E5%8A%A1%E5%99%A8-tcpserver%E5%A4%9A%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%B9%BF%E6%92%AD"&gt;五、控制台版：服务器 Tcpserver（多客户端广播）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%85%AD-gui-%E7%89%88tcp_client"&gt;六、GUI 版：TCP_Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E4%B8%83-gui-%E7%89%88tcp_server"&gt;七、GUI 版：TCP_Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%85%AB%E6%A0%B8%E5%BF%83%E7%9F%A5%E8%AF%86%E7%82%B9%E6%80%BB%E7%BB%93"&gt;八、核心知识点总结&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E4%B9%9D%E4%BB%8A%E5%A4%A9%E8%B8%A9%E7%9A%84%E5%9D%91--%E5%80%BC%E5%BE%97%E6%B3%A8%E6%84%8F%E7%9A%84%E7%82%B9"&gt;九、今天踩的坑 / 值得注意的点&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%8D%81%E8%BF%9B%E9%98%B6%E5%86%99%E6%B3%95%E5%A4%9A%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%B0%81%E8%A3%85-clientconnection-%E6%A8%A1%E5%BC%8F"&gt;十、进阶写法：多客户端封装 ClientConnection 模式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%8D%81%E4%B8%80%E6%98%8E%E5%A4%A9%E5%8F%AF%E4%BB%A5%E5%81%9A%E4%BB%80%E4%B9%88"&gt;十一、明天可以做什么&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="一今天做了什么"&gt;一、今天做了什么&lt;/h2&gt;
&lt;p&gt;用 Qt 实现了 &lt;strong&gt;TCP 客户端 / 服务器&lt;/strong&gt; 双向通信，共 4 个项目：&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;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;TcpSocket&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制台（QCoreApplication）&lt;/td&gt;
&lt;td&gt;客户端&lt;/td&gt;
&lt;td&gt;连接即自动发一条 &amp;ldquo;Hello Server!&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Tcpserver&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制台（QCoreApplication）&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;TCP_Client&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GUI（QWidget）&lt;/td&gt;
&lt;td&gt;客户端&lt;/td&gt;
&lt;td&gt;界面输入 IP/端口，收发消息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TCP_Server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GUI（QWidget）&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;blockquote&gt;
&lt;p&gt;我已有 Qt 基础，但&lt;strong&gt;网络编程是零基础&lt;/strong&gt;。今天的关键收获是建立了&amp;quot;客户端/服务器&amp;quot;模型和 Qt 异步收发的心智模型。&lt;/p&gt;</description></item><item><title>Qt 网络编程学习路线（网络编程零基础视角）</title><link>https://www.sylgalaxy.xyz/posts/qt-network-roadmap/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-network-roadmap/</guid><description>&lt;blockquote&gt;
&lt;p&gt;适用人群：已掌握 Qt 基础（信号槽、事件循环、QWidget），&lt;strong&gt;网络编程零基础&lt;/strong&gt;
适用版本：Qt 6.x（Qt 5 大部分通用）
更新日期：2026-08-19&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#1-%E5%AD%A6%E4%B9%A0%E5%AE%9A%E4%BD%8D%E4%B8%8E%E7%9B%AE%E6%A0%87"&gt;1. 学习定位与目标&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#2-%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E9%9B%B6%E5%9F%BA%E7%A1%80%E5%BF%85%E9%A1%BB%E5%85%88%E6%87%82%E7%9A%84-6-%E4%B8%AA%E6%A6%82%E5%BF%B5"&gt;2. 网络编程零基础必须先懂的 6 个概念&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#3-%E9%98%B6%E6%AE%B5%E4%B8%80tcp-%E7%BC%96%E7%A8%8B%E5%85%A5%E9%97%A8%E7%AC%AC-12-%E5%91%A8"&gt;3. 阶段一：TCP 编程入门（第 1~2 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#4-%E9%98%B6%E6%AE%B5%E4%BA%8Ctcp-%E6%B7%B1%E5%85%A5%E4%B8%8E%E5%AE%9E%E6%88%98%E5%8C%96%E7%AC%AC-34-%E5%91%A8"&gt;4. 阶段二：TCP 深入与实战化（第 3~4 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#5-%E9%98%B6%E6%AE%B5%E4%B8%89udp-%E7%BC%96%E7%A8%8B%E7%AC%AC-5-%E5%91%A8"&gt;5. 阶段三：UDP 编程（第 5 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#6-%E9%98%B6%E6%AE%B5%E5%9B%9Bhttp-%E4%B8%8E%E9%AB%98%E5%B1%82%E7%BD%91%E7%BB%9C%E7%AC%AC-67-%E5%91%A8"&gt;6. 阶段四：HTTP 与高层网络（第 6~7 周）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#7-%E9%98%B6%E6%AE%B5%E4%BA%94%E8%BF%9B%E9%98%B6%E4%B8%8E%E5%AE%89%E5%85%A8%E7%AC%AC-8-%E5%91%A8%E8%B5%B7"&gt;7. 阶段五：进阶与安全（第 8 周起）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#8-%E9%98%B6%E6%AE%B5%E5%85%AD%E5%AE%9E%E6%88%98%E9%A1%B9%E7%9B%AE"&gt;8. 阶段六：实战项目&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#9-%E6%8E%A8%E8%8D%90%E8%B5%84%E6%BA%90"&gt;9. 推荐资源&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#10-%E6%80%BB%E7%BB%93"&gt;10. 总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="1-学习定位与目标"&gt;1. 学习定位与目标&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：你的 Qt 基础（信号槽、事件循环、对象树）是&lt;strong&gt;最大的优势&lt;/strong&gt;——Qt 把网络编程封装成了&amp;quot;发信号 + 收信号&amp;quot;，你要补的不是 C++ 网络 API，而是&lt;strong&gt;网络协议的基本概念&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="11-为什么用-qt-学网络编程"&gt;1.1 为什么用 Qt 学网络编程&lt;/h3&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;/td&gt;
&lt;td&gt;收发数据都靠信号槽触发，不用自己写多线程阻塞 IO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;跨平台&lt;/td&gt;
&lt;td&gt;Windows / Linux / Android 同一套代码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;高层封装&lt;/td&gt;
&lt;td&gt;QTcpSocket / QUdpSocket / QNetworkAccessManager 把 socket API 包装成 Qt 风格&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;与 GUI 天然结合&lt;/td&gt;
&lt;td&gt;收发数据直接刷新界面，客户端/服务器程序最容易做出可视化效果&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="12-和-c-原生-socket-的对比"&gt;1.2 和 C++ 原生 socket 的对比&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;原生 C++（Winsock / POSIX）&lt;/th&gt;
&lt;th&gt;Qt 封装&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket()&lt;/code&gt; / &lt;code&gt;bind()&lt;/code&gt; / &lt;code&gt;listen()&lt;/code&gt; / &lt;code&gt;accept()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;QTcpServer::listen()&lt;/code&gt; / &lt;code&gt;nextPendingConnection()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;connect()&lt;/code&gt; / &lt;code&gt;send()&lt;/code&gt; / &lt;code&gt;recv()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;QTcpSocket::connectToHost()&lt;/code&gt; / &lt;code&gt;write()&lt;/code&gt; / &lt;code&gt;readAll()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&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;code&gt;readyRead&lt;/code&gt; 信号 + &lt;code&gt;readAll()&lt;/code&gt;，&lt;code&gt;errorString()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;结论：&lt;strong&gt;先学概念，再学 Qt API&lt;/strong&gt;。概念（TCP、端口、粘包）是通用的，Qt 只是更友好的实现工具。&lt;/p&gt;</description></item><item><title>qt-doc · Qt 智能文档 Skill</title><link>https://www.sylgalaxy.xyz/posts/ai-qt-doc-readme/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/ai-qt-doc-readme/</guid><description>&lt;p&gt;&lt;strong&gt;不要死记硬背 Qt 类名，告诉它你想干什么。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个为 opencode 设计的 Qt 领域智能体 Skill：你只需要用中文描述需求
（&amp;ldquo;查一下线程怎么用&amp;rdquo;），它会自动映射为 &lt;code&gt;QThread&lt;/code&gt;，抓取官方文档，并返回小白能看懂的核心 API 总结。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这不是搜索引擎，这是一个懂 Qt 的领域智能体。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="-它能做什么"&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;th&gt;示例&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;中文概念自动映射为 Qt 类名&lt;/td&gt;
&lt;td&gt;&amp;ldquo;线程&amp;rdquo; → &lt;code&gt;QThread&lt;/code&gt;，&amp;ldquo;画形状&amp;rdquo; → &lt;code&gt;QPainterPath&lt;/code&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;code&gt;QTcpSocket&lt;/code&gt; 返回整个 &lt;code&gt;QAbstractSocket→QIODevice→QObject&lt;/code&gt; 族，2 个 API → 216 个&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;来源标注&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;每个 API 标注来自哪个类&lt;/td&gt;
&lt;td&gt;&lt;code&gt;connectToHost&lt;/code&gt;（来自 &lt;code&gt;QAbstractSocket&lt;/code&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;在线 → 本地离线文档 → JSON 缓存&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;未开启时零劫持 Web/Java 等非 Qt 问题&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="-快速开始"&gt;🚀 快速开始&lt;/h2&gt;
&lt;h3 id="环境要求"&gt;环境要求&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;li&gt;依赖：&lt;code&gt;requests&lt;/code&gt;、&lt;code&gt;beautifulsoup4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opencode.ai"&gt;opencode&lt;/a&gt;（可选用任意支持 Skill 的 Agent 运行器）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="安装"&gt;安装&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone &amp;lt;your-repo-url&amp;gt; qt-doc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd qt-doc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pip install -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 安装 skill 到 opencode 全局（可选）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp -r qt-doc ~/.config/opencode/skills/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="使用"&gt;使用&lt;/h3&gt;
&lt;p&gt;重启 opencode 后，在会话中：&lt;/p&gt;</description></item><item><title>qt-doc（Qt 智能文档）</title><link>https://www.sylgalaxy.xyz/posts/ai-qt-doc-skill/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/ai-qt-doc-skill/</guid><description>&lt;p&gt;&lt;strong&gt;仅当用户显式要求开启 Qt 专家模式时触发&lt;/strong&gt;，如说&amp;quot;开启Qt专家模式&amp;quot;、&amp;ldquo;进入Qt专家模式&amp;rdquo;、
&amp;ldquo;Qt专家模式&amp;quot;等。&lt;/p&gt;
&lt;p&gt;一旦触发，&lt;strong&gt;本会话进入 Qt 专家模式&lt;/strong&gt;，直到会话结束：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;之后该会话内的所有 Qt/C++ 问题都用本 skill 流程回答（映射类名→抓文档→小白化总结）。&lt;/li&gt;
&lt;li&gt;会话保持生效：通过 &lt;code&gt;/sessions&lt;/code&gt; 恢复该对话，专家模式依然生效。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;新开对话默认不加载本 skill&lt;/strong&gt;，需再次显式开启——实现会话级隔离。&lt;/li&gt;
&lt;li&gt;在专家模式下，非 Qt 的通用编程问题（如 Java/Web）正常回答，不套用 Qt 文档流程。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="流程"&gt;流程&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;把用户描述映射为 Qt 类名（Q 开头）。
&lt;ul&gt;
&lt;li&gt;先查本 skill 目录下的 &lt;code&gt;mapping.json&lt;/code&gt; 精确匹配。&lt;/li&gt;
&lt;li&gt;未命中则凭 Qt 领域知识推断（如&amp;quot;画形状&amp;rdquo;→QPainterPath）。&lt;/li&gt;
&lt;li&gt;无法确定时询问用户。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;调用抓取脚本（可传多个类名，一次抓取）：
&lt;ul&gt;
&lt;li&gt;优先使用环境变量 &lt;code&gt;QT_FETCH_CMD&lt;/code&gt; 指向脚本（如 &lt;code&gt;python /path/to/qt_fetch.py&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;未设置时，用当前仓库内脚本：&lt;code&gt;python &amp;lt;repo&amp;gt;/qt_fetch.py &amp;lt;类名1&amp;gt; &amp;lt;类名2&amp;gt;...&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;示例：&lt;code&gt;python ../qt_fetch.py QThread QTimer&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;读取 stdout JSON。若 &lt;code&gt;errors&lt;/code&gt; 非空，说明该类未找到，提示用户检查拼写或模块。&lt;/li&gt;
&lt;li&gt;基于 JSON 的 &lt;code&gt;title/brief/apis&lt;/code&gt; 做小白化总结。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="输出规范中文开头带-qt-doc"&gt;输出规范（中文，开头带 [qt-doc]）&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;这是什么&lt;/strong&gt;：一句话说明该类用途。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;构造函数&lt;/strong&gt;：核心 1-2 个。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最常用函数&lt;/strong&gt;：数量视类而定——核心常用类 5-8 个，简单类 3-4 个。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关键信号&lt;/strong&gt;：1 个 + 触发时机（有信号时）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;示例代码&lt;/strong&gt;：简短 5-8 行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;⚠️ 注意&lt;/strong&gt;：继承或使用要点。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="继承链"&gt;继承链&lt;/h2&gt;
&lt;p&gt;查询结果含 &lt;code&gt;inheritance_chain&lt;/code&gt;（从派生到基类）与每个 API 的 &lt;code&gt;inheritsFrom&lt;/code&gt; 来源。
若某类 API 很少（如 QTcpSocket），说明它继承自父类，常用函数多在父类文档中——
总结时应说明函数来自哪个父类（如 connectToHost 来自 QAbstractSocket）。&lt;/p&gt;</description></item><item><title>Qt5 信号槽重载与 explicit 关键字详解</title><link>https://www.sylgalaxy.xyz/posts/qt-qt5-signalslot-overload-and/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-qt5-signalslot-overload-and/</guid><description>&lt;blockquote&gt;
&lt;p&gt;适用版本：Qt 5.x / C++14+
更新日期：2026-07-29&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E4%B8%80%E4%BF%A1%E5%8F%B7%E4%B8%8E%E6%A7%BD%E5%87%BD%E6%95%B0%E9%87%8D%E8%BD%BDoverload"&gt;一、信号与槽函数重载（Overload）&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E5%9C%BA%E6%99%AF%E5%81%87%E8%AE%BE"&gt;场景假设&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%96%B9%E6%A1%88%E4%B8%80qoverload--qoverload%E6%9C%80%E6%8E%A8%E8%8D%90"&gt;方案一：QOverload / qOverload（最推荐）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%96%B9%E6%A1%88%E4%BA%8Cstatic_cast-%E6%98%BE%E5%BC%8F%E8%BD%AC%E5%9E%8B"&gt;方案二：static_cast 显式转型&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%96%B9%E6%A1%88%E4%B8%89lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%9C%80%E7%81%B5%E6%B4%BB"&gt;方案三：Lambda 表达式（最灵活）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E4%BF%A1%E5%8F%B7%E5%92%8C%E6%A7%BD%E5%90%8C%E6%97%B6%E9%87%8D%E8%BD%BD%E7%9A%84%E6%B7%B7%E6%90%AD%E5%A4%84%E7%90%86"&gt;信号和槽同时重载的混搭处理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%80%BB%E7%BB%93%E5%BB%BA%E8%AE%AE"&gt;总结建议&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E4%BA%8Cexplicit-%E5%85%B3%E9%94%AE%E5%AD%97%E8%AF%A6%E8%A7%A3"&gt;二、explicit 关键字详解&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#1-%E4%B8%8D%E5%8A%A0-explicit%E5%85%81%E8%AE%B8%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2"&gt;1. 不加 explicit（允许隐式转换）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#2-%E5%8A%A0%E4%B8%8A-explicit%E7%A6%81%E6%AD%A2%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2"&gt;2. 加上 explicit（禁止隐式转换）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#3-qt-%E4%B8%AD%E7%9A%84%E7%BB%8F%E5%85%B8%E5%AE%9E%E6%88%98%E5%9C%BA%E6%99%AF"&gt;3. Qt 中的经典实战场景&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%80%BB%E7%BB%93"&gt;总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="一信号与槽函数重载overload"&gt;一、信号与槽函数重载（Overload）&lt;/h2&gt;
&lt;p&gt;在 Qt5 中，信号和槽函数发生重载是非常常见的场景，也是最容易引起&lt;strong&gt;编译错误&lt;/strong&gt;或&lt;strong&gt;运行时行为不符合预期&lt;/strong&gt;的地方。&lt;/p&gt;
&lt;p&gt;由于 Qt5 使用 &lt;code&gt;&amp;amp;ClassName::functionName&lt;/code&gt; 的新式语法，当遇到重载时，&lt;strong&gt;编译器无法自动推断你要使用哪一个具体的函数指针，因此必须进行强制类型转换或使用 Lambda 表达式来消除歧义。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="场景假设"&gt;场景假设&lt;/h3&gt;
&lt;p&gt;假设有一个类，里面定义了两个重载的普通成员函数（在 Qt5 中都可以当槽）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Receiver&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; QObject
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Q_OBJECT
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 槽函数 1：无参
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; handleUpdate() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; qDebug() &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;无参槽被触发&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 槽函数 2：带一个 int 参数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;handleUpdate&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; value) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; qDebug() &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;带参槽被触发，值为&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; value;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;现在有一个信号想要连接到这个槽，有以下几种方案：&lt;/p&gt;</description></item><item><title>QTabWidget 与 QStackedWidget 的区别及常用方式</title><link>https://www.sylgalaxy.xyz/posts/qt-qtabwidget-vs-qstackedwidget/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-qtabwidget-vs-qstackedwidget/</guid><description>&lt;h2 id="一概述"&gt;一、概述&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;QTabWidget&lt;/code&gt; 和 &lt;code&gt;QStackedWidget&lt;/code&gt; 都是 Qt 中用于&lt;strong&gt;管理多页面切换&lt;/strong&gt;的控件，但它们的设计定位和使用场景有显著区别。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;QTabWidget&lt;/th&gt;
&lt;th&gt;QStackedWidget&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;内置导航&lt;/td&gt;
&lt;td&gt;自带标签栏（Tab Bar）&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;code&gt;setCurrentIndex()&lt;/code&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;需配合其他控件（如 QListWidget）使用&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;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="二qtabwidget--自带标签栏的多页容器"&gt;二、QTabWidget — 自带标签栏的多页容器&lt;/h2&gt;
&lt;h3 id="21-特点"&gt;2.1 特点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;顶部（或底部/左侧/右侧）自带 QTabBar&lt;/li&gt;
&lt;li&gt;每个 Tab 对应一个页面（QWidget 子类）&lt;/li&gt;
&lt;li&gt;点击 Tab 自动切换页面，无需额外代码&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="22-常用方式"&gt;2.2 常用方式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 创建 TabWidget
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QTabWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;tabWidget &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QTabWidget(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 创建页面
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;page1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;page2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 添加页面（传入 widget 和标题）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tabWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addTab(page1, &lt;span style="color:#e6db74"&gt;&amp;#34;基本设置&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tabWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addTab(page2, &lt;span style="color:#e6db74"&gt;&amp;#34;高级设置&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 设置当前页
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tabWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setCurrentIndex(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 常用设置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tabWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setTabPosition(QTabWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;North); &lt;span style="color:#75715e"&gt;// 标签位置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tabWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setTabShape(QTabWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Rounded); &lt;span style="color:#75715e"&gt;// 标签形状
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tabWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setMovable(true);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 信号与槽：标签切换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;connect(tabWidget, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QTabWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;currentChanged, [](&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; index) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; qDebug() &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;切换到第&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; index &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;页&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="三qstackedwidget--无内置导航的页面堆栈"&gt;三、QStackedWidget — 无内置导航的页面堆栈&lt;/h2&gt;
&lt;h3 id="31-特点"&gt;3.1 特点&lt;/h3&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;h3 id="32-常用方式"&gt;3.2 常用方式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 创建 StackedWidget
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QStackedWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;stackedWidget &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QStackedWidget(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 创建页面
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;page1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;page2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;page3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 添加页面（返回 index）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; idx1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stackedWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(page1);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; idx2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stackedWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(page2);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; idx3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stackedWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(page3);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 切换页面
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stackedWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setCurrentIndex(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 按索引切换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stackedWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setCurrentWidget(page3); &lt;span style="color:#75715e"&gt;// 按指针切换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取当前页面
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; currentIdx &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stackedWidget&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;currentIndex();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="33-配合-qlistwidget-实现导航"&gt;3.3 配合 QListWidget 实现导航&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 左侧列表 + 右侧堆栈的经典布局
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QListWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;list &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QListWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;list&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addItem(&lt;span style="color:#e6db74"&gt;&amp;#34;基本设置&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;list&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addItem(&lt;span style="color:#e6db74"&gt;&amp;#34;高级设置&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;list&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addItem(&lt;span style="color:#e6db74"&gt;&amp;#34;关于&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;QStackedWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;stack &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QStackedWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; BasicSettingsPage());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; AdvancedSettingsPage());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; AboutPage());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 连接信号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;connect(list, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QListWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;currentRowChanged,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QStackedWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;setCurrentIndex);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="34-配合-qpushbutton-实现向导流程"&gt;3.4 配合 QPushButton 实现向导流程&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 上一步 / 下一步 向导
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;connect(btnNext, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QPushButton&lt;span style="color:#f92672"&gt;::&lt;/span&gt;clicked, [&lt;span style="color:#f92672"&gt;=&lt;/span&gt;]() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; next &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;currentIndex() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (next &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;count()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setCurrentIndex(next);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;connect(btnPrev, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QPushButton&lt;span style="color:#f92672"&gt;::&lt;/span&gt;clicked, [&lt;span style="color:#f92672"&gt;=&lt;/span&gt;]() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; prev &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;currentIndex() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (prev &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setCurrentIndex(prev);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="四核心区别总结"&gt;四、核心区别总结&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;对比维度&lt;/th&gt;
&lt;th&gt;QTabWidget&lt;/th&gt;
&lt;th&gt;QStackedWidget&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;内置 Tab 栏&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;点击 Tab&lt;/td&gt;
&lt;td&gt;&lt;code&gt;setCurrentIndex()&lt;/code&gt; / &lt;code&gt;setCurrentWidget()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;自定义导航&lt;/td&gt;
&lt;td&gt;受限（可隐藏 Tab 栏）&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;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="如何选择"&gt;如何选择？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;需要标准标签切换 → QTabWidget&lt;/strong&gt;（简单快速）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;需要自定义切换方式 → QStackedWidget&lt;/strong&gt;（如列表导航、按钮翻页）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;需要向导/步骤流程 → QStackedWidget&lt;/strong&gt;（搭配按钮更自然）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;既有标签又想自定义 →&lt;/strong&gt; 用 QTabWidget 隐藏 TabBar + 代码控制切换&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="五完整示例左侧列表--右侧堆栈"&gt;五、完整示例：左侧列表 + 右侧堆栈&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QApplication&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QHBoxLayout&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QListWidget&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QStackedWidget&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QLabel&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; argc, &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;argv[]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QApplication app(argc, argv);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QWidget window;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QHBoxLayout &lt;span style="color:#f92672"&gt;*&lt;/span&gt;layout &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QHBoxLayout(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;window);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 左侧导航
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QListWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;list &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QListWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; list&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addItem(&lt;span style="color:#e6db74"&gt;&amp;#34;页面一&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; list&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addItem(&lt;span style="color:#e6db74"&gt;&amp;#34;页面二&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; list&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addItem(&lt;span style="color:#e6db74"&gt;&amp;#34;页面三&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; list&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;setFixedWidth(&lt;span style="color:#ae81ff"&gt;120&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 右侧页面
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QStackedWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;stack &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QStackedWidget();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QLabel(&lt;span style="color:#e6db74"&gt;&amp;#34;这是页面一的内容&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QLabel(&lt;span style="color:#e6db74"&gt;&amp;#34;这是页面二的内容&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; QLabel(&lt;span style="color:#e6db74"&gt;&amp;#34;这是页面三的内容&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layout&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(list);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; layout&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;addWidget(stack, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; connect(list, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QListWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;currentRowChanged,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stack, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;QStackedWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;setCurrentIndex);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; window.resize(&lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; window.show();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; app.exec();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>QWidget 深入详解</title><link>https://www.sylgalaxy.xyz/posts/qt-qwidget/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/qt-qwidget/</guid><description>&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#1-%E4%BB%80%E4%B9%88%E6%98%AF-qwidget"&gt;1. 什么是 QWidget&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#2-qwidget-%E7%9A%84%E7%BB%A7%E6%89%BF%E4%BD%93%E7%B3%BB"&gt;2. QWidget 的继承体系&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#3-%E5%88%9B%E5%BB%BA%E4%B8%8E%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"&gt;3. 创建与基本使用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#4-%E7%AA%97%E5%8F%A3%E5%B1%9E%E6%80%A7"&gt;4. 窗口属性&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#5-%E5%87%A0%E4%BD%95%E5%B8%83%E5%B1%80%E4%B8%8E%E5%9D%90%E6%A0%87%E7%B3%BB%E7%BB%9F"&gt;5. 几何布局与坐标系统&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#6-%E4%BA%8B%E4%BB%B6%E7%B3%BB%E7%BB%9F"&gt;6. 事件系统&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#7-%E7%BB%98%E5%88%B6%E7%B3%BB%E7%BB%9F"&gt;7. 绘制系统&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#8-%E6%A0%B7%E5%BC%8F%E8%A1%A8-qss"&gt;8. 样式表 (QSS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#9-%E5%B8%83%E5%B1%80%E7%AE%A1%E7%90%86"&gt;9. 布局管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#10-%E5%AD%90%E6%8E%A7%E4%BB%B6%E4%B8%8E%E5%B1%82%E7%BA%A7%E7%AE%A1%E7%90%86"&gt;10. 子控件与层级管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#11-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8E%A7%E4%BB%B6%E5%AE%9E%E6%88%98"&gt;11. 自定义控件实战&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#12-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96"&gt;12. 性能优化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#13-%E5%B8%B8%E8%A7%81%E9%99%B7%E9%98%B1%E4%B8%8E%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5"&gt;13. 常见陷阱与最佳实践&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#14-%E6%80%BB%E7%BB%93"&gt;14. 总结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="1-什么是-qwidget"&gt;1. 什么是 QWidget&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;QWidget&lt;/code&gt; 是 Qt 框架中所有用户界面对象的基类。它既是&amp;quot;控件&amp;quot;（widget），也是&amp;quot;窗口&amp;quot;（window）。在 Qt 的世界里，几乎所有可见元素都是 &lt;code&gt;QWidget&lt;/code&gt;——按钮、标签、输入框、对话框，乃至整个应用程序的主窗口。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：QWidget 是一个&amp;quot;空白的矩形区域&amp;quot;，它知道如何绘制自己、如何处理鼠标键盘事件、如何管理子控件。你可以在它之上构建任意复杂的 UI。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="核心职责"&gt;核心职责&lt;/h3&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;/td&gt;
&lt;td&gt;最小化、最大化、关闭、标题栏&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;绘制&lt;/td&gt;
&lt;td&gt;通过 &lt;code&gt;paintEvent&lt;/code&gt; 自绘外观&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&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;/tr&gt;
&lt;tr&gt;
&lt;td&gt;布局管理&lt;/td&gt;
&lt;td&gt;与 QLayout 协作自动排列子控件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;样式设置&lt;/td&gt;
&lt;td&gt;通过 QSS 或 QPalette 定制外观&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="2-qwidget-的继承体系"&gt;2. QWidget 的继承体系&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;QObject
└── QPaintDevice
└── QWidget ← 本文主角
├── QFrame
│ ├── QLabel
│ ├── QAbstractScrollArea
│ └── ...
├── QAbstractButton
│ ├── QPushButton
│ ├── QCheckBox
│ ├── QRadioButton
│ └── ...
├── QComboBox
├── QLineEdit
├── QSlider
├── QSpinBox
├── QDialog
├── QMainWindow
└── ...
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;QObject&lt;/strong&gt;：提供了信号槽机制、对象树管理、事件过滤器等基础设施。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QPaintDevice&lt;/strong&gt;：声明了&amp;quot;可以被绘制&amp;quot;的能力，提供了绘制设备的抽象接口。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QWidget&lt;/strong&gt;：将两者结合，成为一个&lt;strong&gt;可交互、可绘制、可包含子对象的矩形区域&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="3-创建与基本使用"&gt;3. 创建与基本使用&lt;/h2&gt;
&lt;h3 id="31-最简单的-qwidget"&gt;3.1 最简单的 QWidget&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QApplication&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QWidget&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; argc, &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;argv[])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QApplication app(argc, argv);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QWidget w;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; w.setWindowTitle(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello QWidget&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; w.resize(&lt;span style="color:#ae81ff"&gt;400&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; w.show();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; app.exec();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-创建自定义-qwidget-子类"&gt;3.2 创建自定义 QWidget 子类&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// MyWidget.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#pragma once
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QWidget&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QPainter&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyWidget&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; QWidget
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Q_OBJECT &lt;span style="color:#75715e"&gt;// 启用信号槽、元对象特性
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;explicit&lt;/span&gt; MyWidget(QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;parent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nullptr&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; paintEvent(QPaintEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;event) &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mousePressEvent&lt;/span&gt;(QMouseEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;event) &lt;span style="color:#66d9ef"&gt;override&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// MyWidget.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;#34;MyWidget.h&amp;#34;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;QPainter&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MyWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;MyWidget(QWidget &lt;span style="color:#f92672"&gt;*&lt;/span&gt;parent)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; QWidget(parent)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; setMinimumSize(&lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;150&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; MyWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;paintEvent(QPaintEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; QPainter &lt;span style="color:#a6e22e"&gt;painter&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; painter.setRenderHint(QPainter&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Antialiasing);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; painter.setBrush(QColor(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;150&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; painter.drawRoundedRect(rect().adjusted(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;), &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; MyWidget&lt;span style="color:#f92672"&gt;::&lt;/span&gt;mousePressEvent(QMouseEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;event)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 点击时改变颜色
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Q_UNUSED(event);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; update();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="33-对象树与父子关系"&gt;3.3 对象树与父子关系&lt;/h3&gt;
&lt;p&gt;QWidget 的构造函数接受一个 &lt;code&gt;parent&lt;/code&gt; 参数：&lt;/p&gt;</description></item><item><title>select 多路复用</title><link>https://www.sylgalaxy.xyz/posts/go-03-03-select/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-03-select/</guid><description>&lt;blockquote&gt;
&lt;p&gt;一个 goroutine 同时监听多个 channel 的「事件循环」：C++/epoll 监听多个 fd 的那个心智模型，Go 把它内建成了 select 语句&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;select&lt;/code&gt; 是 Go 语法层面的&lt;strong&gt;多路复用（multiplexing）&lt;strong&gt;原语：它让一个 goroutine 同时&lt;/strong&gt;等待多个 channel 上的收发操作&lt;/strong&gt;，只要其中一个就绪，就走对应的分支。&lt;/p&gt;
&lt;p&gt;对于 C++ 开发者，最贴切的类比是 &lt;strong&gt;Linux epoll / poll&lt;/strong&gt;：你不想为每个 socket 各开一个线程去阻塞读，而是用一个线程同时监听一堆 fd，哪个有事件处理哪个。&lt;code&gt;select&lt;/code&gt; 就是「 goroutine 版本的 epoll」——但它更进一步：它还能同时做&lt;strong&gt;非阻塞尝试&lt;/strong&gt;（default）、&lt;strong&gt;定时超时&lt;/strong&gt;（&lt;code&gt;time.After&lt;/code&gt;）、&lt;strong&gt;动态禁用分支&lt;/strong&gt;（nil channel）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;select&lt;/code&gt; 是「组合 channel 为复杂同步逻辑」的胶水。没有 select，一个 goroutine 只能死等一个 channel；有了 select，你才能写超时、写取消、写事件循环、写多路汇流。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;epoll_wait(fds, ...)&lt;/code&gt; / &lt;code&gt;poll()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;select { case &amp;lt;-ch1: ... }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 是对 channel 通道复用，C++ 是对 fd 复用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;同时等两个事件&lt;/td&gt;
&lt;td&gt;一个线程一个 fd 各睡一觉 / epoll&lt;/td&gt;
&lt;td&gt;一个 goroutine 同时等多个 case&lt;/td&gt;
&lt;td&gt;&lt;code&gt;select&lt;/code&gt; 内建，代码直白得多&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;随机公平选择&lt;/td&gt;
&lt;td&gt;epoll 按就绪顺序返回&lt;/td&gt;
&lt;td&gt;多 case 就绪时&lt;strong&gt;随机&lt;/strong&gt;选一个&lt;/td&gt;
&lt;td&gt;Go 保证公平：随机而非先后&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;非阻塞尝试&lt;/td&gt;
&lt;td&gt;&lt;code&gt;poll(fd, timeout=0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;select { case ...: default: }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;default&lt;/code&gt; = 都不就绪立即走&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;超时等待&lt;/td&gt;
&lt;td&gt;&lt;code&gt;epoll_wait&lt;/code&gt; 的 timeout 参数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;select&lt;/code&gt; + &lt;code&gt;time.After(1s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;超时是普通 channel，不是特殊机制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;收发都监听&lt;/td&gt;
&lt;td&gt;读 / 写事件分别注册&lt;/td&gt;
&lt;td&gt;一个 select 里既有发送又有接收 case&lt;/td&gt;
&lt;td&gt;语法上收发对称&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;监听无限器&lt;/td&gt;
&lt;td&gt;服务端 accept 线程循环&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for { select { ... } }&lt;/code&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;取消注册 fd&lt;/td&gt;
&lt;td&gt;case 的 channel 置 nil → 永久阻塞&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;nil channel 妙用&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-select-基本语法"&gt;3.1 select 基本语法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ch1&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ch2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 两个 goroutine 各自往不同 channel 发&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;() { &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Millisecond&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;ch1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;来自 ch1&amp;#34;&lt;/span&gt; }()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;() { &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;300&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Millisecond&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;ch2&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;来自 ch2&amp;#34;&lt;/span&gt; }()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// select 会阻塞，直到某个 case 就绪&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;select&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ch1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;收到:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 大概率先到 ch1（100ms 更快）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ch2&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;收到:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;要点&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>sync 包（WaitGroup / Mutex / Once）</title><link>https://www.sylgalaxy.xyz/posts/go-03-04-sync-waitgroup-mutex-once/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-04-sync-waitgroup-mutex-once/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 的 std::thread::join、std::mutex、std::once_flag，Go 用 sync 包给了一套轻量且更安全的等价物&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sync&lt;/code&gt; 包是 Go 标准库的&lt;strong&gt;同步原语仓库&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;th&gt;C++ 对应&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sync.WaitGroup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;等一批 goroutine 全部结束&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::thread::join&lt;/code&gt;（一次等多个）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sync.Mutex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;互斥锁&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::mutex&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sync.RWMutex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读写锁&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::shared_mutex&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sync.Once&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只执行一次（懒加载 / 单例）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::once_flag&lt;/code&gt; + &lt;code&gt;std::call_once&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sync.Map&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;并发安全的 map（特化场景）&lt;/td&gt;
&lt;td&gt;手写 lock + &lt;code&gt;std::map&lt;/code&gt; / 无直接对应&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sync.Cond&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;条件变量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::condition_variable&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go 的哲学是「尽量用 channel」，但&lt;strong&gt;同步原语&lt;/strong&gt;（锁 / 分组等待 / 只跑一次）仍然有明确位置。与 C++ 的锁相比，Go 的锁&lt;strong&gt;不可拷贝&lt;/strong&gt;、有 &lt;code&gt;defer&lt;/code&gt; 配合的极简用法、内置检测工具，心智负担小得多。本笔记重点讲 WaitGroup、Mutex / RWMutex、Once，并简述 errgroup。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;t.join()&lt;/code&gt;（单个）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;wg := sync.WaitGroup{}; wg.Add(1); defer wg.Done(); wg.Wait()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;WaitGroup 一次等&lt;strong&gt;一批&lt;/strong&gt;，Add 要提前&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;互斥锁&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::mutex m; m.lock(); m.unlock();&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var mu sync.Mutex; mu.Lock(); defer mu.Unlock()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 惯例用 &lt;code&gt;defer&lt;/code&gt; 解锁，防漏&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;锁唯一性&lt;/td&gt;
&lt;td&gt;lock 传递没意义&lt;/td&gt;
&lt;td&gt;结构体字段还是值？&lt;strong&gt;拷贝锁 = 复制已锁状态 → 编译常见错&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Go 锁内含 &lt;code&gt;noCopy&lt;/code&gt;，拷贝会被提示&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;只初始化一次&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::once_flag&lt;/code&gt; + &lt;code&gt;std::call_once&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var once sync.Once; once.Do(func(){...})&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 写进一个 &lt;code&gt;Do&lt;/code&gt;，天然幂等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;读写锁&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::shared_mutex&lt;/code&gt;（C++17）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sync.RWMutex&lt;/code&gt; + &lt;code&gt;RLock()/RUnlock()&lt;/code&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;code&gt;std::recursive_mutex&lt;/code&gt; 才行&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Mutex 不可重入&lt;/strong&gt;，同 goroutine 再锁 = 自锁死&lt;/td&gt;
&lt;td&gt;Go 明确拒绝重入，倒逼更好的设计&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;条件变量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::condition_variable&lt;/code&gt; + predicate 循环&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sync.Cond&lt;/code&gt;（少见）或直接 channel&lt;/td&gt;
&lt;td&gt;Go 社区倾向 channel 代替 cond&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;分组错误传播&lt;/td&gt;
&lt;td&gt;手写 &lt;code&gt;std::future&lt;/code&gt; 收集异常&lt;/td&gt;
&lt;td&gt;&lt;code&gt;errgroup.Group&lt;/code&gt;（&lt;code&gt;golang.org/x/sync&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;Go 有现成库，等全部且带首个错误&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-syncwaitgroup等一批-goroutine"&gt;3.1 sync.WaitGroup：等一批 goroutine&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;worker&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;sync&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WaitGroup&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Done&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// 结束前把计数器减 1（defer 保证即使中途 panic 也会减，避免死锁）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;worker %d 开始\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Millisecond&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 模拟干活&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;worker %d 结束\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sync&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WaitGroup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// ⚠️ Add 必须在 go 之前！计数器先 +1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;worker&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 注意传指针：WaitGroup 内部要改计数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;wg&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Wait&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// 阻塞直到所有 Done，相当于「等这一批全部 join」&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;所有 worker 都结束了&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;WaitGroup 规则&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>unsafe 与 cgo 互操作</title><link>https://www.sylgalaxy.xyz/posts/go-06-07-unsafe-cgo/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-06-07-unsafe-cgo/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 的 &lt;code&gt;reinterpret_cast&lt;/code&gt; + &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; 在 Go 里被装进了两个官方包：&lt;code&gt;unsafe&lt;/code&gt;（打破类型/GC 规则）和 &lt;code&gt;cgo&lt;/code&gt;（跨语言边界）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 追求内存安全，但现实里有三类需求绕不开&amp;quot;不安全&amp;quot;：&lt;strong&gt;解析二进制布局&lt;/strong&gt;、&lt;strong&gt;优化热路径&lt;/strong&gt;、&lt;strong&gt;调用 C 库&lt;/strong&gt;。Go 给的两把钥匙：&lt;code&gt;unsafe&lt;/code&gt; 包的 &lt;code&gt;unsafe.Pointer&lt;/code&gt; 允许你绕过类型系统（但仍受 GC 语义约束），&lt;code&gt;cgo&lt;/code&gt; 允许你直接调用 C 函数（&lt;code&gt;import &amp;quot;C&amp;quot;&lt;/code&gt; + &lt;code&gt;//export&lt;/code&gt; 双向互操作）。本章把两者的语义、内存规则、坑、风险一次性讲透——很多线上故障就是从&amp;quot;玩 unsafe 没算清 GC&amp;quot;或&amp;quot;cgo 调用频繁导致线程放大&amp;quot;开始的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;unsafe.Pointer&lt;/code&gt; 像&amp;quot;元指针&amp;quot;，可被 GC 追踪；&lt;code&gt;uintptr&lt;/code&gt; 只是整数，&lt;strong&gt;GC 不追踪&lt;/strong&gt;——所以不允许&amp;quot;把指针存成 uintptr 长期持有&amp;quot;。&lt;code&gt;cgo&lt;/code&gt; 让你调 C，但每次调用都伴随 goroutine 栈切换与可能的线程膨胀，且 &lt;code&gt;C.CString&lt;/code&gt; 分配的内存必须自己 &lt;code&gt;C.free&lt;/code&gt;。&lt;code&gt;CGO_ENABLED=0&lt;/code&gt; 是纯静态交叉编译的开关，代价是放弃 cgo。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;reinterpret_cast&amp;lt;T*&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unsafe.Pointer&lt;/code&gt; 转换&lt;/td&gt;
&lt;td&gt;Go 的三步规则更受限，且有 GC 约束&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型大小&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sizeof(T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unsafe.Sizeof(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一样，但 Go 的 &lt;code&gt;Sizeof&lt;/code&gt; 返回 &lt;code&gt;uintptr&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;对齐要求&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alignof(T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unsafe.Alignof(x)&lt;/code&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;code&gt;offsetof&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unsafe.Offsetof(s.F)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 对嵌套/嵌入结构有规则限制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;指针算术&lt;/td&gt;
&lt;td&gt;&lt;code&gt;p + n&lt;/code&gt;（任意）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uintptr(p) + n&lt;/code&gt; 转回&lt;/td&gt;
&lt;td&gt;Go 用 uintptr 防 GC 丢对象（坑）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;跨语言符号&lt;/td&gt;
&lt;td&gt;&lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;//export&lt;/code&gt; / 声明&lt;/td&gt;
&lt;td&gt;Go 还自动处理了 C 的 ABI 与参数传值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;头文件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#include&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// #include &amp;lt;...&amp;gt;&lt;/code&gt; 注释块 + &lt;code&gt;import &amp;quot;C&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;cgo 注释必须紧跟 import&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C 字符串生命周期&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::string&lt;/code&gt;/手管 char*&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C.CString&lt;/code&gt; → &lt;code&gt;C.free&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 里 C 内存在你的掌控（GC 不管）&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;code&gt;//export&lt;/code&gt; 导出给 C&lt;/td&gt;
&lt;td&gt;回调时 cgo 会切换刻意绑的线程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;交叉编译&lt;/td&gt;
&lt;td&gt;工具链编译 C 代码&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CGO_ENABLED=0&lt;/code&gt; 纯 Go&lt;/td&gt;
&lt;td&gt;纯 Go 无 cgo 才能一路交叉到底&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-unsafe-包三件套sizeof--alignof--offsetof"&gt;3.1 &lt;code&gt;unsafe&lt;/code&gt; 包三件套：Sizeof / Alignof / Offsetof&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;unsafe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Header&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Magic&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;uint16&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 2 字节&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Flags&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 1 字节&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;uint32&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 4 字节（需要对齐）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;h&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Header&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Sizeof:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;unsafe&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sizeof&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;h&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 8（不是 2+1+4=7，有 padding）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Alignof:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;unsafe&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Alignof&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;h&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 4（最大成员对齐）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Offsetof Magic:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;unsafe&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Offsetof&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;h&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Magic&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Offsetof Flags:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;unsafe&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Offsetof&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;h&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Flags&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Offsetof Body:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;unsafe&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Offsetof&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;h&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 4（3 处 padding 1 字节填在中间）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Offsetof&lt;/code&gt; 要求字段是&lt;strong&gt;可寻址&lt;/strong&gt;的（&lt;code&gt;s.F&lt;/code&gt; 形式，不能是未导出字段）。&lt;/li&gt;
&lt;li&gt;这些原语从 1.0 至今，官方 docs 明确：&lt;strong&gt;&lt;code&gt;unsafe&lt;/code&gt; 不提供兼容性承诺&lt;/strong&gt;，后续版本可能变——但在已知版本内是可靠的。&lt;/li&gt;
&lt;li&gt;C++ 对照：&lt;code&gt;sizeof/alignof/offsetof&lt;/code&gt; 早已内建，返回 &lt;code&gt;size_t&lt;/code&gt;；Go 返回 &lt;code&gt;uintptr&lt;/code&gt;。&lt;strong&gt;布局算法的直觉（对齐、padding）两者完全一致&lt;/strong&gt;——你可以把你对 C++ 结构体内存布局的知识直接迁移过来。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="32-unsafepointer-与-uintptr-的区别本章最核心"&gt;3.2 &lt;code&gt;unsafe.Pointer&lt;/code&gt; 与 &lt;code&gt;uintptr&lt;/code&gt; 的区别（本章最核心）&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;&lt;code&gt;unsafe.Pointer&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;uintptr&lt;/code&gt;&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;code&gt;*T&lt;/code&gt; 同族）&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;整数&lt;/strong&gt;（地址的编号）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GC 追踪&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;code&gt;+n&lt;/code&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;✅（Go 1.17+ 合法）&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;code&gt;*T&lt;/code&gt; ↔ &lt;code&gt;unsafe.Pointer&lt;/code&gt; ↔ &lt;code&gt;*U&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uintptr(unsafe.Pointer(...))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;unsafe&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Pointer&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;amp;x 是 *int → unsafe.Pointer（合法）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;up&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; uintptr(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 转成整数（此时&amp;#34;失去指针身份&amp;#34;）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ⚠️ 一旦 p 指向的对象被 GC 移动/回收，up 就是&amp;#34;悬垂整数&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Go 的 GC 不移动对象，但会回收；up 长期保存=访问已释放内存（未定义行为）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;官方三步规则&lt;/strong&gt;（Go 文档的『Conversion』/『Restrictions』，一共 7 条），核心是三种合法模式：&lt;/p&gt;</description></item><item><title>VS 向导 vs CMake 手建工程：一次取舍记录</title><link>https://www.sylgalaxy.xyz/posts/env-vs-wizard-or-cmake/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/env-vs-wizard-or-cmake/</guid><description>&lt;p&gt;新建 C++ 项目时，用 VS2022 项目向导，还是手建目录 + CMake？核心结论：&lt;strong&gt;向导是「快」，CMake 手建是「稳」；长期维护的 Boost + OpenCV 项目走 CMake 手建路线。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="一完全不利用-vs-向导指什么"&gt;一、「完全不利用 VS 向导」指什么&lt;/h2&gt;
&lt;p&gt;VS 新建项目时，向导会自动生成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目录结构&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.vcxproj&lt;/code&gt; / &lt;code&gt;.sln&lt;/code&gt;&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;code&gt;CMakeLists.txt&lt;/code&gt;、用 VS 的「打开文件夹」模式加载。&lt;/p&gt;
&lt;h2 id="二cmake-手建的好处"&gt;二、CMake 手建的好处&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;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;结构清晰、可控&lt;/td&gt;
&lt;td&gt;向导生成的项目，目录和配置是向导定的；手建时 &lt;code&gt;src/&lt;/code&gt;、&lt;code&gt;include/&lt;/code&gt;、&lt;code&gt;resources/&lt;/code&gt;、&lt;code&gt;tests/&lt;/code&gt; 怎么分，自己说了算&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;跨平台&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CMakeLists.txt&lt;/code&gt; 是跨平台的：同一个项目，Windows 用 MSVC，WSL 用 GCC，不用改任何东西；向导生成的 &lt;code&gt;.vcxproj&lt;/code&gt; 只能在 VS 里用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;依赖管理统一&lt;/td&gt;
&lt;td&gt;Boost、OpenCV 全走 &lt;code&gt;find_package&lt;/code&gt;，环境变量一配，所有项目通用；向导的项目要手动一个个加 include、lib 路径&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;不污染仓库&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.vcxproj&lt;/code&gt;、&lt;code&gt;.sln&lt;/code&gt;、&lt;code&gt;.vs/&lt;/code&gt;、&lt;code&gt;out/&lt;/code&gt; 都是本地文件，不进 Git；CMake 项目只需提交 &lt;code&gt;CMakeLists.txt&lt;/code&gt; 和源码，干净&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;和工业界一致&lt;/td&gt;
&lt;td&gt;大多数 C++ 开源项目、跨平台项目都用 CMake；养成这个习惯，以后参与别人的项目、或自己发布项目，都顺&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;配置一次、项目复用&lt;/td&gt;
&lt;td&gt;环境变量和 &lt;code&gt;CMakeLists.txt&lt;/code&gt; 模板定好后，新建项目就是复制模板、改项目名、加源文件。&lt;strong&gt;增量配置，不是每次从零配&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="三cmake-手建的代价"&gt;三、CMake 手建的代价&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;初期配置复杂&lt;/strong&gt;。第一次要理解：&lt;code&gt;CMakeLists.txt&lt;/code&gt; 的语法、&lt;code&gt;find_package&lt;/code&gt; 怎么找库、环境变量怎么设、&lt;code&gt;CMakePresets.json&lt;/code&gt; 的格式。这些概念对新手是门槛。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VS 集成不如原生项目「顺滑」&lt;/strong&gt;。向导项目是 VS 原生支持，调试、IntelliSense 开箱即用；CMake 项目通过「打开文件夹」或「CMake 项目」模式支持，功能也全，但偶尔会遇到配置识别问题。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调试和 IDE 功能偶有摩擦&lt;/strong&gt;。断点、监视窗口、调用栈这些都没问题；但某些 VS 特有的功能（比如某些项目属性页面），在 CMake 项目里没有对应入口。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;学习曲线&lt;/strong&gt;。要同时学 CMake、学 Boost/OpenCV 的 CMake 配置。&lt;strong&gt;一次性投入大，但长期收益高。&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="四取舍小结"&gt;四、取舍小结&lt;/h2&gt;
&lt;p&gt;整体体验是：&lt;strong&gt;结构清晰，配置相对复杂；不过做项目时配置一次，后续只是增量配置。&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>VS2022 打开 CMake 项目的调试说明：断点与 launch.vs.json</title><link>https://www.sylgalaxy.xyz/posts/env-vs-cmake-debug/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/env-vs-cmake-debug/</guid><description>&lt;p&gt;手建的 CMake 项目在 VS2022「打开文件夹」模式下的打开方式、自动生成的配置、断点调试与 &lt;code&gt;launch.vs.json&lt;/code&gt;。核心结论：&lt;strong&gt;CMake 项目的调试体验与向导项目基本一致，唯一多出的一步是手动选启动目标。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="一怎么用-vs-打开手建的-cmake-项目"&gt;一、怎么用 VS 打开手建的 CMake 项目&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;步骤：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;VS2022 → &lt;strong&gt;文件 → 打开 → 文件夹&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;选项目根目录，比如 &lt;code&gt;&amp;lt;项目根目录&amp;gt;\MyProject&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;VS 自动识别 &lt;code&gt;CMakeLists.txt&lt;/code&gt;，切换到 &lt;strong&gt;CMake 项目模式&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;VS 会自动做的事：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;读 &lt;code&gt;CMakeLists.txt&lt;/code&gt;，配置 CMake。&lt;/li&gt;
&lt;li&gt;在项目根目录生成 &lt;code&gt;.vs/&lt;/code&gt;，存 VS 自己的状态。&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;out/build/&lt;/code&gt; 下生成构建产物。&lt;/li&gt;
&lt;li&gt;底部状态栏出现 &lt;strong&gt;配置选择器&lt;/strong&gt;（Debug/Release），和 &lt;strong&gt;CMake 目标选择器&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;和向导项目一样，VS 该自动生成的还是会生成。&lt;/p&gt;
&lt;h2 id="二vs-自动生成的配置有哪些"&gt;二、VS 自动生成的配置有哪些&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;和向导项目时一样：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;.vs/&lt;/code&gt;&lt;/strong&gt;：VS 的工作状态、索引、窗口布局。不提交 Git。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;out/&lt;/code&gt;&lt;/strong&gt;：CMake 构建产物。不提交 Git。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;CMakeUserPresets.json&lt;/code&gt;&lt;/strong&gt;：如果在 VS 里改过预设，它可能生成这个。不提交 Git。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;这些不影响项目结构本身&lt;/strong&gt;，只是 VS 的本地缓存，删了能重建。&lt;/p&gt;
&lt;h2 id="三断点怎么用"&gt;三、断点怎么用&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;CMake 项目的断点和向导项目完全一样。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="基本流程"&gt;基本流程&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;在代码行号左边点一下&lt;/strong&gt;，出现红点，就是断点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;按 F5&lt;/strong&gt; 启动调试（不是 Ctrl+F5，Ctrl+F5 是不调试直接运行）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;程序运行到断点处停下&lt;/strong&gt;，VS 自动切换到调试界面。&lt;/li&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;/ol&gt;
&lt;h3 id="常用快捷键"&gt;常用快捷键&lt;/h3&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;/td&gt;
&lt;td&gt;&lt;code&gt;F5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;停止调试&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Shift + F5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单步跳过（不进入函数）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;F10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单步进入（进入函数）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;F11&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;跳出当前函数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Shift + F11&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;继续运行&lt;/td&gt;
&lt;td&gt;&lt;code&gt;F5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;切换断点&lt;/td&gt;
&lt;td&gt;&lt;code&gt;F9&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;条件断点&lt;/td&gt;
&lt;td&gt;右键断点 → 条件&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="cmake-项目特有的注意点"&gt;CMake 项目特有的注意点&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 启动目标&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Web 框架 Gin / Echo</title><link>https://www.sylgalaxy.xyz/posts/go-05-03-web-gin-echo/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-05-03-web-gin-echo/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 Crow / Drogon 到 Go：Gin 是什么、何时该用它，以及它替你省下的那些 net/http 样板代码&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;上一篇我们把 net/http 摸了一遍——纯标准库完全能写服务，但路由到参数、JSON 绑定校验、中间件这些「每个项目都要重复一遍」的活，写得多了就烦。Gin 和 Echo 是 Go 生态里最主流的两个 Web 框架，它们把「路由分组 + 参数绑定 + 校验 + 中间件」整合成统一 API。Gin 以高性能（基于 radix tree 的路由器）和极简 API 出名，Echo 结构更规整、前后端感触更「框架味」。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：框架不改变 Go 的 Web 本质——底层还是 &lt;code&gt;http.Handler&lt;/code&gt;；Gin/Echo 只是给你一个更顺手的 &lt;code&gt;c *gin.Context&lt;/code&gt; / &lt;code&gt;e echo.Context&lt;/code&gt;。「参数绑定 + binding tag 校验」是 C++ 框架（如 Drogon）很难优雅做到的事，Go 用结构体标签声明式解决，这是最大的体验提升点。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Web 框架&lt;/td&gt;
&lt;td&gt;Crow / Drogon / cpp-httplib&lt;/td&gt;
&lt;td&gt;Gin / Echo&lt;/td&gt;
&lt;td&gt;Gin 性能强、Echo 规整&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;路由注册&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CROW_ROUTE(app, &amp;quot;/x&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;r.GET(&amp;quot;/x&amp;quot;, fn)&lt;/code&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;code&gt;CROW_ROUTE(app,&amp;quot;/&amp;lt;int&amp;gt;&amp;quot;)&lt;/code&gt; 回调参数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c.Param(&amp;quot;id&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;参数进 Handler 上下文&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;code&gt;r.Group(&amp;quot;/api&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;组内共享中间件/前缀&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON 返回&lt;/td&gt;
&lt;td&gt;&lt;code&gt;app.route(...).post(...)&lt;/code&gt; 手动拼&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c.JSON(200, obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一行返回+自动 Content-Type&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;code&gt;c.ShouldBindJSON(&amp;amp;req)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;结构体 tags 声明式映射&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;参数校验&lt;/td&gt;
&lt;td&gt;手写 if 判断&lt;/td&gt;
&lt;td&gt;&lt;code&gt;binding:&amp;quot;required&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;tag 驱动，绑定即校验&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;code&gt;r.Use(mw)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;全局/组/路由三级粒度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;panic 恢复&lt;/td&gt;
&lt;td&gt;手动 try/catch&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gin.Recovery()&lt;/code&gt; 内置&lt;/td&gt;
&lt;td&gt;框架默认就带&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-gin-起步--一个能跑的-hello"&gt;3.1 Gin 起步 —— 一个能跑的 Hello&lt;/h3&gt;
&lt;p&gt;安装并写最小服务：&lt;/p&gt;</description></item><item><title>Windows 上 Boost + OpenCV + CMake 的环境配置方案：只配两件事</title><link>https://www.sylgalaxy.xyz/posts/env-cmake-boost-opencv-setup/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/env-cmake-boost-opencv-setup/</guid><description>&lt;p&gt;从零配置的一套通用方案：&lt;strong&gt;环境变量 + CMakePresets.json&lt;/strong&gt;。一次配好，所有项目通用。Windows 端只配 Boost + OpenCV，不配 Qt（Qt 开发放在 Linux 端）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;文中 &lt;code&gt;&amp;lt;OpenCV安装目录&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;Boost根目录&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;项目根目录&amp;gt;&lt;/code&gt; 为占位符，替换成本机实际目录即可。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="一环境变量系统变量"&gt;一、环境变量（系统变量）&lt;/h2&gt;
&lt;p&gt;在 Windows「系统属性 → 环境变量」里，&lt;strong&gt;系统变量&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;th&gt;作用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OpenCV_DIR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\lib&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OpenCV 的 &lt;code&gt;Config.cmake&lt;/code&gt; 所在目录&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BOOST_ROOT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Boost根目录&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Boost 根目录&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;PATH 追加&lt;/strong&gt;（运行时找 dll）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\bin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Boost 不用加 PATH&lt;/strong&gt;，静态库，运行时不需要 dll。&lt;/p&gt;
&lt;h2 id="二每个库的配置细节"&gt;二、每个库的配置细节&lt;/h2&gt;
&lt;h3 id="opencv"&gt;OpenCV&lt;/h3&gt;
&lt;p&gt;关键文件（示例路径）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\lib\OpenCVConfig.cmake
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\lib\opencv_world4100.lib
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\lib\opencv_world4100d.lib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;变量：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;OpenCV_DIR = &amp;lt;OpenCV安装目录&amp;gt;\build\x64\vc16\lib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CMake 里：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cmake" data-lang="cmake"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;find_package(&lt;span style="color:#e6db74"&gt;OpenCV&lt;/span&gt; &lt;span style="color:#e6db74"&gt;REQUIRED&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target_include_directories(&lt;span style="color:#e6db74"&gt;main&lt;/span&gt; &lt;span style="color:#e6db74"&gt;PRIVATE&lt;/span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;OpenCV_INCLUDE_DIRS&lt;span style="color:#f92672"&gt;}&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target_link_libraries(&lt;span style="color:#e6db74"&gt;main&lt;/span&gt; &lt;span style="color:#e6db74"&gt;PRIVATE&lt;/span&gt; &lt;span style="color:#f92672"&gt;${&lt;/span&gt;OpenCV_LIBS&lt;span style="color:#f92672"&gt;}&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="boost"&gt;Boost&lt;/h3&gt;
&lt;p&gt;关键文件（示例路径）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;Boost根目录&amp;gt;\stage\lib\cmake\Boost-1.81.0\BoostConfig.cmake
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;Boost根目录&amp;gt;\stage\lib\libboost_filesystem-vc143-mt-x64-1_81.lib
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;Boost根目录&amp;gt;\stage\lib\libboost_filesystem-vc143-mt-gd-x64-1_81.lib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;变量：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;BOOST_ROOT = &amp;lt;Boost根目录&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CMake 里：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cmake" data-lang="cmake"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;Boost_NO_SYSTEM_PATHS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;Boost_USE_STATIC_LIBS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set(&lt;span style="color:#e6db74"&gt;Boost_USE_MULTITHREADED&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ON&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;find_package(&lt;span style="color:#e6db74"&gt;Boost&lt;/span&gt; &lt;span style="color:#e6db74"&gt;1.81&lt;/span&gt; &lt;span style="color:#e6db74"&gt;REQUIRED&lt;/span&gt; &lt;span style="color:#e6db74"&gt;COMPONENTS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;filesystem&lt;/span&gt; &lt;span style="color:#e6db74"&gt;system&lt;/span&gt; &lt;span style="color:#e6db74"&gt;thread&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;target_link_libraries(&lt;span style="color:#e6db74"&gt;main&lt;/span&gt; &lt;span style="color:#e6db74"&gt;PRIVATE&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Boost::filesystem&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Boost::system&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Boost::thread&lt;/span&gt;)&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：Boost 大部分是 header-only，&lt;code&gt;find_package&lt;/code&gt; 只对&lt;strong&gt;需要编译的库&lt;/strong&gt;（&lt;code&gt;filesystem&lt;/code&gt;、&lt;code&gt;system&lt;/code&gt;、&lt;code&gt;thread&lt;/code&gt; 等）起作用。header-only 的库直接 &lt;code&gt;#include&lt;/code&gt; 就行，CMake 里不用 &lt;code&gt;find_package&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>包与导入</title><link>https://www.sylgalaxy.xyz/posts/go-01-09/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-09/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的&amp;quot;包&amp;quot;是组织代码的唯一单元。一个目录就是一个包，没有头文件，没有 &lt;code&gt;.cpp&lt;/code&gt;/&lt;code&gt;.h&lt;/code&gt; 分离。
理解包的规则，是读懂 Go 项目结构的第一步。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="1-核心概念速览"&gt;1. 核心概念速览&lt;/h2&gt;
&lt;h3 id="package-声明"&gt;package 声明&lt;/h3&gt;
&lt;p&gt;每个 &lt;code&gt;.go&lt;/code&gt; 文件的&lt;strong&gt;第一行&lt;/strong&gt;必须是 &lt;code&gt;package&lt;/code&gt; 声明，且同一目录下所有文件必须声明&lt;strong&gt;相同的包名&lt;/strong&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 文件: mathutil/add.go&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mathutil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 同目录的 subtract.go 也必须是:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// package mathutil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="package-main--程序入口"&gt;package main — 程序入口&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;package main&lt;/code&gt; 是特殊约定，表示&lt;strong&gt;可执行程序&lt;/strong&gt;的入口，不是库包。Go 没有独立的入口函数声明——入口就是 &lt;code&gt;package main&lt;/code&gt; 里的 &lt;code&gt;func main()&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello, Go!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;C++ 对照: &lt;code&gt;package main&lt;/code&gt; ≈ 包含 &lt;code&gt;int main()&lt;/code&gt; 的那个编译单元。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="2-c-对照速查表"&gt;2. C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Go 概念&lt;/th&gt;
&lt;th&gt;C++ 对应&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;package&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;namespace&lt;/code&gt; + &lt;code&gt;#include&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一个 package 同时提供命名空间和导入功能，不需要头文件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;import&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#include&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;import 加载的是编译好的包，不是文本包含&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;首字母大写 = 导出&lt;/td&gt;
&lt;td&gt;&lt;code&gt;public&lt;/code&gt; / &lt;code&gt;protected&lt;/code&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;code&gt;private&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;同上，没有 &lt;code&gt;private&lt;/code&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;同目录必须同 package，不可混装&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;init()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;全局变量的构造函数&lt;/td&gt;
&lt;td&gt;更可靠，保证在 &lt;code&gt;main()&lt;/code&gt; 之前执行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;import . &amp;quot;fmt&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;using namespace std;&lt;/code&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;code&gt;#include&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;两者都是编译错误&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;internal/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;C++ 无直接对应&lt;/td&gt;
&lt;td&gt;类似 &lt;code&gt;friend&lt;/code&gt; 的简化版，限制子包的可见性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;go.mod&lt;/code&gt; 依赖管理&lt;/td&gt;
&lt;td&gt;CMake / Conan / vcpkg&lt;/td&gt;
&lt;td&gt;Go 原生支持，无需第三方工具&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="3-导入语法"&gt;3. 导入语法&lt;/h2&gt;
&lt;h3 id="单行导入"&gt;单行导入&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;单行导入&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="分组导入推荐"&gt;分组导入（推荐）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;strings&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 标准库放一组&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Join&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Args&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:], &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;C++ 对照: Go 的 &lt;code&gt;import&lt;/code&gt; 会自动加载包内所有导出符号，不需要逐个 include 头文件。&lt;/p&gt;</description></item><item><title>包与模块</title><link>https://www.sylgalaxy.xyz/posts/go-extra-08/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-08/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的包组织、可见性规则与模块系统深入&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一包package基础"&gt;一、包（Package）基础&lt;/h2&gt;
&lt;h3 id="11-什么是包"&gt;1.1 什么是包&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 每个 Go 文件都必须声明自己属于哪个包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt; &lt;span style="color:#75715e"&gt;// main 包是可执行程序的入口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 同一目录下的所有 .go 文件必须属于同一个包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 例外：_test.go 文件可以声明 _test 包（用于黑盒测试）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-包的命名规则"&gt;1.2 包的命名规则&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 包名：小写单词，不要下划线或驼峰&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mypackage&lt;/span&gt; &lt;span style="color:#75715e"&gt;// ✅&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my_package&lt;/span&gt; &lt;span style="color:#75715e"&gt;// ❌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyPackage&lt;/span&gt; &lt;span style="color:#75715e"&gt;// ❌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 目录名 = 包名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// src/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// └── utils/ // 目录名 utils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ├── string.go // package utils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// └── math.go // package utils&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-main-包的特殊性"&gt;1.3 main 包的特殊性&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// main 包 + main() 函数 = 可执行程序&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="二导入import"&gt;二、导入（Import）&lt;/h2&gt;
&lt;h3 id="21-基本导入"&gt;2.1 基本导入&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 标准库&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/gin-gonic/gin&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 第三方包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 批量导入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="22-导入别名"&gt;2.2 导入别名&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 解决包名冲突&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;myfmt&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/other/fmt&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 别名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="23-点导入与下划线导入"&gt;2.3 点导入与下划线导入&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 点导入：将包的导出标识符引入当前命名空间&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; . &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 不需要 fmt.Println&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ⚠️ 不推荐使用——降低代码可读性&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 下划线导入：只执行包的 init() 函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/go-sql-driver/mysql&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 注册 MySQL 驱动&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 不使用包中的任何标识符，只是让 init() 被调用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="三可见性规则大小写"&gt;三、可见性规则（大小写）&lt;/h2&gt;
&lt;h3 id="31-导出规则"&gt;3.1 导出规则&lt;/h3&gt;
&lt;p&gt;Go &lt;strong&gt;没有 public/private 关键字&lt;/strong&gt;，通过&lt;strong&gt;首字母大小写&lt;/strong&gt;控制可见性：&lt;/p&gt;</description></item><item><title>变量、常量与类型</title><link>https://www.sylgalaxy.xyz/posts/go-01-02/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-02/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 到 Go：变量声明、常量、基本类型与类型系统的核心差异&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 的类型系统比 C++ &lt;strong&gt;更简单、更严格&lt;/strong&gt;：没有隐式类型转换，没有函数重载，没有模板/泛型（Go 1.18 后有泛型但用法不同）。这看似&amp;quot;退步&amp;quot;，实际上大幅降低了代码的心智负担——编译器替你做了大量约束。&lt;/p&gt;
&lt;p&gt;对于 C++ 开发者，最需要适应的三个变化：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;所有未使用的变量都会报错&lt;/strong&gt;（&lt;code&gt;unused variable&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型转换必须显式&lt;/strong&gt;（没有 &lt;code&gt;int x = 3.14&lt;/code&gt; 这种事）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;string&lt;/code&gt; 是值类型&lt;/strong&gt;（赋值和传参都会拷贝，不像 &lt;code&gt;std::string&lt;/code&gt; 有引用计数）&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;int x;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var x int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 声明与赋值分离&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型推断&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto x = 42;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x := 42&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:=&lt;/code&gt; = 声明 + 推断 + 赋值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;常量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;const int X = 10;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;const X = 10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 常量不需要写类型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;编译期常量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;constexpr int X = 10;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;const X = 10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 的 &lt;code&gt;const&lt;/code&gt; 全部是编译期常量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;枚举&lt;/td&gt;
&lt;td&gt;&lt;code&gt;enum Color { RED, GREEN };&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;const ( RED = iota; GREEN )&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 用 &lt;code&gt;iota&lt;/code&gt; 实现枚举&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;隐式转换&lt;/td&gt;
&lt;td&gt;&lt;code&gt;double d = 42;&lt;/code&gt;（合法）&lt;/td&gt;
&lt;td&gt;不允许&lt;/td&gt;
&lt;td&gt;Go 必须显式：&lt;code&gt;float64(42)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;字符串&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::string s = &amp;quot;hi&amp;quot;;&lt;/code&gt;（引用语义）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;s := &amp;quot;hi&amp;quot;&lt;/code&gt;（值类型）&lt;/td&gt;
&lt;td&gt;Go string 赋值是拷贝&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;字符&lt;/td&gt;
&lt;td&gt;&lt;code&gt;char c = 'A';&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var c byte = 'A'&lt;/code&gt; 或 &lt;code&gt;var c rune = 'A'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 没有 &lt;code&gt;char&lt;/code&gt; 类型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多变量声明&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int a, b;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var a, b int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;或 &lt;code&gt;a, b := 1, 2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;零值&lt;/td&gt;
&lt;td&gt;未初始化（UB/随机值）&lt;/td&gt;
&lt;td&gt;自动零值&lt;/td&gt;
&lt;td&gt;Go 所有变量声明后都有零值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型别名&lt;/td&gt;
&lt;td&gt;&lt;code&gt;using MyInt = int;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;type MyInt int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 叫&amp;quot;类型定义&amp;quot;，不是别名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;打印&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::cout &amp;lt;&amp;lt; x;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Println(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 用 &lt;code&gt;fmt&lt;/code&gt; 包格式化输出&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三变量声明"&gt;三、变量声明&lt;/h2&gt;
&lt;h3 id="31-var-声明"&gt;3.1 &lt;code&gt;var&lt;/code&gt; 声明&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 基本语法：var 变量名 类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 声明但不赋值，零值为 &amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 零值为 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;active&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 零值为 false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 声明并赋值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;score&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;lang&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 类型推断：省略类型，编译器从右侧推断&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;version&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 推断为 int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pi&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;3.14&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 推断为 float64（Go 默认浮点类型）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;greeting&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 推断为 string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;active&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;score&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;lang&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;version&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;pi&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;greeting&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;C++ 对照&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>变量与类型</title><link>https://www.sylgalaxy.xyz/posts/go-extra-02/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-02/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的变量声明、基本类型与类型系统基础&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一变量声明"&gt;一、变量声明&lt;/h2&gt;
&lt;p&gt;Go 是&lt;strong&gt;静态类型&lt;/strong&gt;语言——变量的类型在编译时确定。&lt;/p&gt;
&lt;h3 id="11-四种声明方式"&gt;1.1 四种声明方式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 1. var 显式声明（指定类型）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 2. var 显式声明（类型推断）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 3. := 短变量声明（最常用，只能在函数内使用）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 4. var 批量声明&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;175.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;isGo&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12--的限制"&gt;1.2 := 的限制&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ✅ 函数内部 — 可以用 :=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ❌ 包级别 — 不能用 :=，必须用 var&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;globalVar&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// globalVar := &amp;#34;fail&amp;#34; // 编译错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-零值"&gt;1.3 零值&lt;/h3&gt;
&lt;p&gt;Go 中&lt;strong&gt;未赋值的变量自动初始化为零值&lt;/strong&gt;（不是 undefined 或 null）：&lt;/p&gt;</description></item><item><title>标准库核心包：fmt / strings / os / io / time</title><link>https://www.sylgalaxy.xyz/posts/go-02-04-fmt-strings-os-io/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-02-04-fmt-strings-os-io/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 iostream / string / fstream / chrono 到 Go 标准库核心包&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 标准库是&amp;quot;开箱即用&amp;quot;的典范——网络、JSON、加密、压缩、时间、文件全都在标准库里。本笔记聚焦日常开发最高频的 5 个包：&lt;code&gt;fmt&lt;/code&gt;（格式化）、&lt;code&gt;strings&lt;/code&gt;（字符串）、&lt;code&gt;os&lt;/code&gt;（文件/环境）、&lt;code&gt;io&lt;/code&gt;（读写抽象）、&lt;code&gt;time&lt;/code&gt;（时间）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：这些包配合 Go 的&amp;quot;接口即抽象&amp;quot;哲学（&lt;code&gt;io.Reader&lt;/code&gt; / &lt;code&gt;io.Writer&lt;/code&gt;），形成了统一的数据流处理模型——&lt;strong&gt;你写的函数只需要面向接口，就能处理文件、内存、网络任何来源&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::cout &amp;lt;&amp;lt; x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Println(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 内置格式动词&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;格式化字符串&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sprintf(buf, &amp;quot;%d&amp;quot;, x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Sprintf(&amp;quot;%d&amp;quot;, x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;返回 string，无缓冲区&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;字符串操作&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::string&lt;/code&gt; / &lt;code&gt;&amp;lt;cstring&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;strings&lt;/code&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;code&gt;s1 + s2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;strings.Join&lt;/code&gt; / &lt;code&gt;strings.Builder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;大量拼接用 Builder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;文件读取&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::ifstream&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;os.Open&lt;/code&gt; + &lt;code&gt;io.ReadAll&lt;/code&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;code&gt;std::ofstream&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;os.WriteFile&lt;/code&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;code&gt;std::chrono::system_clock::now()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;time.Now()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;返回 Time 结构体&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;休眠&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::this_thread::sleep_for&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;time.Sleep&lt;/code&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;code&gt;std::chrono::duration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;time.Since(t)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;返回 Duration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三fmt--格式化"&gt;三、fmt —— 格式化&lt;/h2&gt;
&lt;h3 id="31-输出函数"&gt;3.1 输出函数&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Print&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;b&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 无换行、无空格: ab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;b&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 空格分隔 + 换行: a b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s %d&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;go&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 格式化: go 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 返回字符串版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s-%d&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;v&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;v-3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-常用格式动词"&gt;3.2 常用格式动词&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;动词&lt;/th&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;%v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;默认格式（任意类型）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Printf(&amp;quot;%v&amp;quot;, 42)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%+v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;结构体带字段名&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Printf(&amp;quot;%+v&amp;quot;, p)&lt;/code&gt; → &lt;code&gt;{Name:tom Age:18}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%#v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 语法表示&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Printf(&amp;quot;%#v&amp;quot;, p)&lt;/code&gt; → &lt;code&gt;main.Person{Name:&amp;quot;tom&amp;quot;}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;类型&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Printf(&amp;quot;%T&amp;quot;, 42)&lt;/code&gt; → &lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;十进制整数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;42&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;十六进制&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2a&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%f&lt;/code&gt; / &lt;code&gt;%.2f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;浮点 / 保留两位&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3.14&lt;/code&gt; / &lt;code&gt;3.14&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字符串&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;hello&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%q&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;带引号字符串&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;hello&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;布尔&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指针地址&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xc0000b2000&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="33-对齐与宽度"&gt;3.3 对齐与宽度&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%-10s|%10s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// left | right&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%05d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 00042（前导零）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="四strings--字符串处理"&gt;四、strings —— 字符串处理&lt;/h2&gt;
&lt;p&gt;Go 的 &lt;code&gt;string&lt;/code&gt; 是不可变值类型，所有操作都返回新字符串。&lt;/p&gt;</description></item><item><title>并发编程基础</title><link>https://www.sylgalaxy.xyz/posts/go-extra-09/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-09/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Goroutine、Channel、Select——Go 并发的核心原语&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一goroutine"&gt;一、Goroutine&lt;/h2&gt;
&lt;h3 id="11-什么是-goroutine"&gt;1.1 什么是 Goroutine&lt;/h3&gt;
&lt;p&gt;Goroutine 是 Go 运行时管理的轻量级线程。创建成本极低（约 2KB 栈空间），可以轻松创建成千上万个。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 启动一个 goroutine：在函数调用前加 go 关键字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;doSomething&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;running in goroutine&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-基本使用"&gt;1.2 基本使用&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;printNumbers&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Millisecond&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;number: %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;printLetters&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;e&amp;#39;&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;150&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Millisecond&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;letter: %c\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;printNumbers&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// 并发执行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;printLetters&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// 并发执行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Second&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 等待 goroutine 完成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;done&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 输出交错出现：number: 1, letter: a, number: 2, letter: b...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-主-goroutine-与-waitgroup"&gt;1.3 主 Goroutine 与 WaitGroup&lt;/h3&gt;
&lt;p&gt;上面用 &lt;code&gt;time.Sleep&lt;/code&gt; 等待是不可靠的。正确做法是用 &lt;code&gt;sync.WaitGroup&lt;/code&gt;：&lt;/p&gt;</description></item><item><title>并发模式（worker pool / 扇入扇出 / pipeline）</title><link>https://www.sylgalaxy.xyz/posts/go-03-07-workerpool-pipeline/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-07-workerpool-pipeline/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 里要自己造轮子的线程池、任务队列、流水线，Go 用 channel 组合出几种固定范式，一次学会受用终生&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;「并发模式」不是语法，而是被反复验证有效的&lt;strong&gt;编排范式&lt;/strong&gt;。Go 里它们几乎全由 channel + goroutine 组合而成：worker pool（工人池）、fan-out（扇出）、fan-in（扇入 / 汇聚）、pipeline（流水线）、限速器（rate limit）、错误传播。&lt;/p&gt;
&lt;p&gt;对于 C++ 开发者，这些模式你多半见过、也手动实现过：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模式&lt;/th&gt;
&lt;th&gt;C++ 里怎么做的&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::thread&lt;/code&gt; 数组 + &lt;code&gt;std::queue&lt;/code&gt; 任务 + mutex 守卫&lt;/td&gt;
&lt;td&gt;线程生命周期、任务派发、锁竞争都要自己管&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;扇出&lt;/td&gt;
&lt;td&gt;把一个大任务拆 N 份发给 N 线程&lt;/td&gt;
&lt;td&gt;怎么「等所有分片」+ 汇总&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;流水线&lt;/td&gt;
&lt;td&gt;每个 stage 一个线程 + 队列 + condvar&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;p&gt;Go 里这些平均不到 30 行，且&lt;strong&gt;语义全部显式可见&lt;/strong&gt;。本笔记不讲抽象，直接给 6 个能 &lt;code&gt;go run&lt;/code&gt; 的模板。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：所有模式都建立在「&lt;strong&gt;channel 即队列 + 同步&lt;/strong&gt;」之上。模式 = 固定形状的 channel 拓扑 + 一组约定（谁 close、谁 range、谁 Wait）。&lt;/p&gt;</description></item><item><title>测试：单元、表格驱动、基准、覆盖率</title><link>https://www.sylgalaxy.xyz/posts/go-04-02/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-02/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 GTest 到 Go testing 标准库：约定优于配置，表格驱动是 Go 的灵魂测试法&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 把测试框架内置为标准库 &lt;code&gt;testing&lt;/code&gt;，&lt;strong&gt;零配置&lt;/strong&gt;、约定驱动：文件以 &lt;code&gt;_test.go&lt;/code&gt; 结尾，函数名 &lt;code&gt;TestXxx(t *testing.T)&lt;/code&gt; 即被测对象。不需要 GTest 那样的宏和注册表，&lt;code&gt;go test&lt;/code&gt; 一条命令跑全部测试。&lt;/p&gt;
&lt;p&gt;C++ 开发者上手 GTest 要经历「链接 gtest、写 TEST 宏、配 CMake、起 runner」；Go 则是「建 &lt;code&gt;_test.go&lt;/code&gt;、写 &lt;code&gt;func TestXxx(t *testing.T)&lt;/code&gt;、&lt;code&gt;go test&lt;/code&gt;」。**表格驱动测试（table-driven tests）**是 Go 社区最推崇的测试形态——本质是把断言与数据分离，让测试用例变成一张表。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;testing&lt;/code&gt; 包只给了「基础骨架」（&lt;code&gt;t&lt;/code&gt; 的各种方法），断言与 mock 不内置——这是 Go 的极简哲学。但配合表格驱动 + 子测试 + 基准 + 覆盖率，能覆盖绝大多数项目需求。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;GoogleTest / Catch2（第三方）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;testing&lt;/code&gt; 标准库&lt;/td&gt;
&lt;td&gt;零依赖、零配置，&lt;code&gt;go test&lt;/code&gt; 即跑&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;测试文件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test_xxx.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xxx_test.go&lt;/code&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;code&gt;TEST(Suite, Name)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func TestXxx(t *testing.T)&lt;/code&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;code&gt;EXPECT_EQ&lt;/code&gt; / &lt;code&gt;ASSERT_EQ&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t.Errorf&lt;/code&gt; / &lt;code&gt;t.Fatal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 里就是普通方法调用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;致命 vs 非致命&lt;/td&gt;
&lt;td&gt;ASSERT（终止）vs EXPECT（继续）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t.Fatal&lt;/code&gt;（终止）vs &lt;code&gt;t.Errorf&lt;/code&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;SCOPED_TRACE 近似&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t.Run(&amp;quot;name&amp;quot;, ...)&lt;/code&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;GTEST 参数化 P 复杂&lt;/td&gt;
&lt;td&gt;切片 + for 循环&lt;/td&gt;
&lt;td&gt;语言特性天然支持，无需框架&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基准测试&lt;/td&gt;
&lt;td&gt;Google Benchmark&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BenchmarkXxx(b *testing.B)&lt;/code&gt; + &lt;code&gt;b.N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;benchmark 内建&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;覆盖率&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-fprofile-arcs&lt;/code&gt; + gcov/lcov&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go test -cover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一条命令带 HTML 输出&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据竞态检测&lt;/td&gt;
&lt;td&gt;TSan（需编译期开启）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go test -race&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;运行时内建，跨平台&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-单元测试最小形态"&gt;3.1 单元测试最小形态&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;calc.go&lt;/code&gt; 旁边放 &lt;code&gt;calc_test.go&lt;/code&gt;：&lt;/p&gt;</description></item><item><title>测试与工程实践</title><link>https://www.sylgalaxy.xyz/posts/go-extra-10/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-10/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的内置测试框架、代码规范与工程化实践&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一单元测试"&gt;一、单元测试&lt;/h2&gt;
&lt;h3 id="11-测试文件命名"&gt;1.1 测试文件命名&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// 测试文件以 _test.go 结尾
math.go → math_test.go
user.go → user_test.go
utils/string.go → utils/string_test.go
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="12-基本测试函数"&gt;1.2 基本测试函数&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// math.go&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;math&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// math_test.go&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;math&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TestAdd&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;T&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Add(1, 2) = %d; want 3&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 运行测试&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// go test ./...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// go test -v ./...（详细输出）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-table-driven-tests表驱动测试"&gt;1.3 Table-Driven Tests（表驱动测试）&lt;/h3&gt;
&lt;p&gt;Go 社区最推崇的测试模式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TestAdd&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;T&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;tests&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;expected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;positive numbers&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;negative numbers&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;zero&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;mixed&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;tests&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Run&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;T&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;expected&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Add(%d, %d) = %d; want %d&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;expected&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 运行特定子测试&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// go test -run TestAdd/positive_numbers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="14-测试辅助函数"&gt;1.4 测试辅助函数&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 断言辅助函数（Go 标准库没有内置 assert，但可以自己写）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;assertEqual&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;T&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;got&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;want&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt;{}) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Helper&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// 标记为辅助函数，错误信息显示调用者行号&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;got&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;want&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;got %v, want %v&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;got&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;want&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TestAdd&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;T&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;assertEqual&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;), &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;t.Helper()&lt;/code&gt;&lt;/strong&gt;：标记辅助函数，错误时显示调用方的行号而非辅助函数内部行号。&lt;/p&gt;</description></item><item><title>常用工具 gofmt/vet/doc/交叉编译</title><link>https://www.sylgalaxy.xyz/posts/go-04-04-gofmt-vet-doc/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-04-gofmt-vet-doc/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 clang-format/clang-tidy/doxygen 到 Go 内建工具链：规范靠工具强制，而非风格文档&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 的工具链是「一个 &lt;code&gt;go&lt;/code&gt; 命令 + 若干子命令」的整体。&lt;code&gt;gofmt&lt;/code&gt; 统一代码格式、&lt;code&gt;go vet&lt;/code&gt; 做静态检查、&lt;code&gt;go doc&lt;/code&gt; 生成/查看文档、&lt;code&gt;go build&lt;/code&gt; 配合环境变量实现交叉编译。与 C++ 需要 &lt;code&gt;clang-format&lt;/code&gt; + &lt;code&gt;clang-tidy&lt;/code&gt; + &lt;code&gt;doxygen&lt;/code&gt; + 一堆脚本不同，&lt;strong&gt;Go 把规范内置&lt;/strong&gt;——&lt;code&gt;gofmt&lt;/code&gt; 的格式无人争论，因为唯一标准。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;gofmt&lt;/code&gt; 从 Go 项目诞生起就存在，&lt;code&gt;go fmt&lt;/code&gt; 只是 go 工具链对它的子命令封装，两者格式化结果一致；真正的工程价值是让「风格讨论」从代码评审里消失——C++ 团队为空格和括号开过的会，在 Go 里不存在。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;clang-format（需 .clang-format 配置）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gofmt&lt;/code&gt; / &lt;code&gt;go fmt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;零配置&lt;/strong&gt;，官方唯一风格&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;静态检查&lt;/td&gt;
&lt;td&gt;clang-tidy / cppcheck&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go vet&lt;/code&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;doxygen（注释标记 + 配置）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go doc&lt;/code&gt; + &lt;code&gt;godoc&lt;/code&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;code&gt;///&lt;/code&gt;、块注释 + doxygen 指令&lt;/td&gt;
&lt;td&gt;成对注释（块首选）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// 名称 描述&lt;/code&gt; 约定，导出符号必须注释&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;交叉编译&lt;/td&gt;
&lt;td&gt;每平台一套交叉工具链/CI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOOS=linux GOARCH=amd64 go build&lt;/code&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;code&gt;-static&lt;/code&gt; / 静态库手动组合&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CGO_ENABLED=0&lt;/code&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;code&gt;-s&lt;/code&gt; strip 符号&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-ldflags &amp;quot;-s -w&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;编译期传递 linker 参数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;依赖清理&lt;/td&gt;
&lt;td&gt;CMake/vcpkg 手工重配&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go mod tidy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与工具链一体&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-gofmt--go-fmt官方格式"&gt;3.1 gofmt / go fmt：官方格式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 查看差异（不修改）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gofmt -l . &lt;span style="color:#75715e"&gt;# 列出格式不达标的文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gofmt -d file.go &lt;span style="color:#75715e"&gt;# 输出 diff 视角的差异&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 覆盖写文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gofmt -w file.go
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go fmt ./... &lt;span style="color:#75715e"&gt;# 等价于 gofmt -w，作用于当前包全部 .go&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# gofmt 不影响语义：只重排缩进、对齐、换行、导入块&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关键规则（&lt;strong&gt;你不需要背，工具会改&lt;/strong&gt;）：&lt;/p&gt;</description></item><item><title>错误处理</title><link>https://www.sylgalaxy.xyz/posts/go-extra-05/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-05/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的错误处理哲学：error 是值，不是异常&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一go-的错误处理哲学"&gt;一、Go 的错误处理哲学&lt;/h2&gt;
&lt;h3 id="11-与异常机制的区别"&gt;1.1 与异常机制的区别&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;Go（error）&lt;/th&gt;
&lt;th&gt;Java/Python（异常）&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;try-catch 机制&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;可以不 catch&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;h3 id="12-核心原则"&gt;1.2 核心原则&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Go 的错误处理模式：每个可能出错的调用都检查返回值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;doSomething&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 处理错误：记录日志、返回错误、终止程序等&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;doSomething failed: %w&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 继续正常逻辑&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Go 的哲学：显式胜于隐式。&lt;/strong&gt; 没有隐藏的控制流，错误路径一目了然。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二error-接口"&gt;二、error 接口&lt;/h2&gt;
&lt;h3 id="21-error-的定义"&gt;2.1 error 的定义&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 标准库中 error 的定义（非常简洁）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;任何实现了 &lt;code&gt;Error() string&lt;/code&gt; 方法的类型都是一个 error：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 自定义错误类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ValidationError&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Field&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Message&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ValidationError&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Error&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;validation failed on field &amp;#39;%s&amp;#39;: %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Field&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Message&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ValidationError&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Field&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Message&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;invalid format&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// validation failed on field &amp;#39;email&amp;#39;: invalid format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="22-创建错误的几种方式"&gt;2.2 创建错误的几种方式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 1. errors.New：简单的静态错误消息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ErrNotFound&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;errors&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;New&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;not found&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用时&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ErrNotFound&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 处理特定错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 2. fmt.Errorf：格式化错误消息（最常用）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;user %d not found&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;userID&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 3. %w 动词：包装（wrap）另一个错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getUser&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;db&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Query&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;getUser(%d): %w&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// %w 保留了原始错误，可以用 errors.Is/As 检查&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;user&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 4. 自定义错误类型（携带结构化信息）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 见上方 ValidationError 示例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="三错误处理模式"&gt;三、错误处理模式&lt;/h2&gt;
&lt;h3 id="31-基本模式"&gt;3.1 基本模式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 模式1：检查并返回&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;processFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;reading %s: %w&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 处理 data...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 成功时返回 nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 模式2：检查并记录日志 + 继续&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetchConfig&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;config fetch failed, using defaults: %v&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;defaultConfig&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 模式3：检查并终止&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Open&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;critical.txt&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;无法打开关键文件:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-错误链error-wrapping"&gt;3.2 错误链（Error Wrapping）&lt;/h3&gt;
&lt;p&gt;Go 1.13+ 支持&lt;strong&gt;错误包装&lt;/strong&gt;，可以构建错误链：&lt;/p&gt;</description></item><item><title>错误处理：error / panic / recover</title><link>https://www.sylgalaxy.xyz/posts/go-02-02-error-panic-recover/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-02-02-error-panic-recover/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 try/catch/throw 到 Go 的显式错误返回值、panic 与 defer+recover&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 的错误处理哲学和 C++ &lt;strong&gt;完全相反&lt;/strong&gt;：不抛异常，而是把错误当作&lt;strong&gt;普通返回值&lt;/strong&gt;显式传递。函数签名里直接写明&amp;quot;可能返回错误&amp;quot;，调用方必须处理。这套设计的核心目标：&lt;strong&gt;错误路径在代码里一目了然，绝不静默吞掉&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Go 提供三层错误机制：&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;th&gt;类似 C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;error&lt;/code&gt; 返回值&lt;/td&gt;
&lt;td&gt;可预期、应处理的错误（文件不存在、网络失败…）&lt;/td&gt;
&lt;td&gt;返回码 / &lt;code&gt;std::error_code&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;panic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;不可恢复的严重错误（越界、空指针…）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;throw&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;在 defer 中捕获 panic&lt;/td&gt;
&lt;td&gt;&lt;code&gt;catch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：能用 &lt;code&gt;error&lt;/code&gt; 就不要 &lt;code&gt;panic&lt;/code&gt;。&lt;code&gt;panic&lt;/code&gt; 是&amp;quot;程序无法继续&amp;quot;的最后手段，&lt;code&gt;recover&lt;/code&gt; 只用于极少数场景（如防止 goroutine 崩溃拖垮整个程序）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;throw std::runtime_error(&amp;quot;...&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;return errors.New(&amp;quot;...&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 是返回值，不是跳转&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;捕获错误&lt;/td&gt;
&lt;td&gt;&lt;code&gt;try { } catch (const std::exception&amp;amp; e)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;if err != nil { ... }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 用 if 判断&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;code&gt;error&lt;/code&gt; 接口&lt;/td&gt;
&lt;td&gt;Go 只有一个 error 接口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;清理资源&lt;/td&gt;
&lt;td&gt;RAII / 析构&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defer&lt;/code&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;code&gt;std::terminate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;panic&lt;/code&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;code&gt;catch (...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defer func() { recover() }()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;recover 必须在 defer 中&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;code&gt;fmt.Errorf(&amp;quot;%w&amp;quot;, err)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%w&lt;/code&gt; 支持解包判断&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三error-接口"&gt;三、error 接口&lt;/h2&gt;
&lt;p&gt;Go 的 &lt;code&gt;error&lt;/code&gt; 是一个&lt;strong&gt;预定义接口&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>达梦数据库学习路线（Qt/C++ 电力运维场景）</title><link>https://www.sylgalaxy.xyz/posts/db-dameng-roadmap/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/db-dameng-roadmap/</guid><description>&lt;h2 id="背景定位"&gt;背景定位&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;电力设备运维场景：变电站设备经 IEC 104 规约报文上送遥测/遥信数据，需要采集、解析并落库存储。&lt;/li&gt;
&lt;li&gt;Qt/C++ 开发背景（Qtc++）：以 Qt 技术栈（MVC、QSqlDatabase、ODBC）为主线承载数据库操作与界面联动。&lt;/li&gt;
&lt;li&gt;国产数据库达梦（DM8）学习：从连接、SQL 到运维全链路，教学过程中与 MySQL 持续对比，突出差异。&lt;/li&gt;
&lt;li&gt;业务代码可用伪代码表述，重点放在数据库讲解的详细性上（驱动、连接、语法、事务、运维）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="章节规划"&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;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;01&lt;/td&gt;
&lt;td&gt;Qt-MVC与达梦数据库集成&lt;/td&gt;
&lt;td&gt;QSqlTableModel/QSqlQueryModel/QSqlRelationalTableModel + ODBC 连接达梦，报文解析→落库→界面刷新链路&lt;/td&gt;
&lt;td&gt;✅ 已写&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;02&lt;/td&gt;
&lt;td&gt;连接与驱动&lt;/td&gt;
&lt;td&gt;ODBC 驱动安装、连接串、QSqlDatabase 建立流程、达梦 COMPATIBLE_MODE 兼容模式&lt;/td&gt;
&lt;td&gt;⬜ 待写&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;03&lt;/td&gt;
&lt;td&gt;基础SQL与MySQL对比&lt;/td&gt;
&lt;td&gt;数据类型、建库建表、CRUD、达梦特有语法（如 DUAL、序列）、MySQL 迁移工具&lt;/td&gt;
&lt;td&gt;⬜ 待写&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;04&lt;/td&gt;
&lt;td&gt;IEC104规约报文实战&lt;/td&gt;
&lt;td&gt;104 规约帧格式详解、报文解析、达梦落库、与界面联动&lt;/td&gt;
&lt;td&gt;⬜ 待写&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05&lt;/td&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;h2 id="学习路径建议"&gt;学习路径建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;先读 01 建立「报文→数据库→界面」整体认识，理解全链路数据流向。&lt;/li&gt;
&lt;li&gt;再补 02/03 打牢连接与 SQL 基础，掌握 ODBC 驱动与达梦语法特性。&lt;/li&gt;
&lt;li&gt;04 回到报文实战深挖规约，将解析与落库结合，完成闭环。&lt;/li&gt;
&lt;li&gt;05 面向生产运维，覆盖事务、存储过程与备份恢复等工程落地能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="进度表"&gt;进度表&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;当前进度：01 已写，其余四章待写，按上表顺序推进。&lt;/li&gt;
&lt;li&gt;本路线图随笔记进度持续更新，每完成一章即同步修订状态列。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>反射（reflection）</title><link>https://www.sylgalaxy.xyz/posts/go-06-06-reflection/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-06-06-reflection/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 的 RTTI 只能拿到 &lt;code&gt;typeid&lt;/code&gt;/&lt;code&gt;dynamic_cast&lt;/code&gt; 少许信息；Go 的 &lt;code&gt;reflect&lt;/code&gt; 能在运行时查看、遍历、修改任意类型与值&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;反射（reflection）&lt;/strong&gt;：程序在运行时检查自身的类型与结构，并据此做动态操作。Go 里就是 &lt;code&gt;reflect&lt;/code&gt; 包：给你 &lt;code&gt;reflect.Type&lt;/code&gt;（类型信息）和 &lt;code&gt;reflect.Value&lt;/code&gt;（一段具体值），能动态读字段、读 tag、调方法、甚至&lt;strong&gt;修改可设置的值&lt;/strong&gt;。序列化库（encoding/json）、ORM、配置解析、测试断言统统建立在这套 API 之上。但反射有显著的性能代价与脆弱性——本章教你怎么用、什么时候值得用。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：反射的入口是 &lt;code&gt;reflect.TypeOf&lt;/code&gt; / &lt;code&gt;reflect.ValueOf&lt;/code&gt;，一切操作都围着这两个对象转；&lt;strong&gt;可设置性（CanSet）&lt;/strong&gt; 是反射修值的前提（变量要可寻址）；&lt;strong&gt;三大定律&lt;/strong&gt;是官方给的使用边界。对 C++ 来说，&lt;code&gt;typeid&lt;/code&gt;/&lt;code&gt;dynamic_cast&lt;/code&gt; 只能做&amp;quot;类型识别&amp;quot;，Go 反射还能&amp;quot;改值、建新值、动态调用&amp;quot;，范围大得多，代价也大得多。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;typeid(x).name()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reflect.TypeOf(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;C++ 只给名字，Go 给结构、字段、方法全图&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;运行时类型转换&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dynamic_cast&amp;lt;T&amp;gt;&lt;/code&gt;（须多态）&lt;/td&gt;
&lt;td&gt;首选类型断言 &lt;code&gt;x.(T)&lt;/code&gt;；reflect 侧有 &lt;code&gt;Type.AssignableTo&lt;/code&gt; / &lt;code&gt;ConvertibleTo&lt;/code&gt; / &lt;code&gt;Implements&lt;/code&gt; 做判断、&lt;code&gt;Value.Convert&lt;/code&gt; 做转换&lt;/td&gt;
&lt;td&gt;Go 反射不要求继承，直接看类型；reflect 包&lt;strong&gt;没有&lt;/strong&gt; &lt;code&gt;AssertableTo&lt;/code&gt; 方法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;遍历字段&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boost::pfr&lt;/code&gt;/手写&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reflect.Value.NumField/Field&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 原生支持任意结构体遍历&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;读字段 tag&lt;/td&gt;
&lt;td&gt;无标准机制&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reflect.StructTag.Get&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 的 struct tag 是反射的主要消费场景&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;动态改值&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*T&lt;/code&gt; + &lt;code&gt;reinterpret_cast&lt;/code&gt; 危险操作&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reflect.Value.Set*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 有 &lt;code&gt;CanSet&lt;/code&gt; 检查，越界即 panic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;动态调用方法&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::invoke&lt;/code&gt;（C++17，仍要具体类型）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reflect.Value.Method(i).Call(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 无需编译期函数指针，纯运行时&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;创建新实例&lt;/td&gt;
&lt;td&gt;&lt;code&gt;T{}&lt;/code&gt; 写死 / 工厂模式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reflect.New(T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;反射可&amp;quot;凭空造值&amp;quot;，C++ 做不到通用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;性能&lt;/td&gt;
&lt;td&gt;零开销（编译期类型）&lt;/td&gt;
&lt;td&gt;每次反射调用开销 ~几百 ns 起&lt;/td&gt;
&lt;td&gt;Go 反射充满动态分派与检查&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;应用场景&lt;/td&gt;
&lt;td&gt;typeid 用于调试/序列化&lt;/td&gt;
&lt;td&gt;序列化/ORM/测试/DI&lt;/td&gt;
&lt;td&gt;反射生态在 Go 里是日常&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型断言&lt;/td&gt;
&lt;td&gt;C++ 无&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x.(T)&lt;/code&gt; 是内置语法&lt;/td&gt;
&lt;td&gt;注意反射 &lt;code&gt;TypeOf&lt;/code&gt; + 断言可以互相换算&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-反射两大入口type-与-value"&gt;3.1 反射两大入口：Type 与 Value&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;reflect&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;name&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;age&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;小甲&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reflect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TypeOf&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 类型信息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reflect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ValueOf&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 值信息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Type:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// main.Person&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Kind:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Kind&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// struct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Value:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// {小甲 18}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;TypeOf(v):&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Type&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// main.Person&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;reflect.Type&lt;/code&gt;&lt;/strong&gt;：描述&amp;quot;类型是什么&amp;quot;——包名、名称、Kind、字段列表、方法集、是否可比较等。URI：&lt;code&gt;t.NumField()&lt;/code&gt;、&lt;code&gt;t.Field(i)&lt;/code&gt;、&lt;code&gt;t.Method(i)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;reflect.Value&lt;/code&gt;&lt;/strong&gt;：描述&amp;quot;这段值是什么&amp;quot;——包含了底层值，可读可设（受 &lt;code&gt;CanSet&lt;/code&gt; 约束）、可调方法、可转 interface。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Kind()&lt;/code&gt;&lt;/strong&gt;：底层类别（&lt;code&gt;Int&lt;/code&gt;、&lt;code&gt;String&lt;/code&gt;、&lt;code&gt;Slice&lt;/code&gt;、&lt;code&gt;Struct&lt;/code&gt;、&lt;code&gt;Map&lt;/code&gt; 等 26 种）。&lt;code&gt;Type&lt;/code&gt; 是具体类型（&lt;code&gt;main.Person&lt;/code&gt;），&lt;code&gt;Kind&lt;/code&gt; 是粗类别（&lt;code&gt;struct&lt;/code&gt;）——C++ 里没有直接对应，最接近 &lt;code&gt;typeid&lt;/code&gt; 得不到 Kind；Go 里 &lt;code&gt;Kind&lt;/code&gt; 用于判断&amp;quot;数据结构形状&amp;quot;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="32-从-value-取回具体值interface"&gt;3.2 从 Value 取回具体值：&lt;code&gt;Interface()&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reflect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ValueOf&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 把 Value 还原成 interface{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Interface&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 再断言回具体类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;p2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;.(&lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p2&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 小甲&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;老代码里 &lt;code&gt;v.Interface()&lt;/code&gt; + 类型断言是组合拳；Go 1.x 有 &lt;code&gt;v.CanInterface()&lt;/code&gt; 检查（未导出字段、&lt;code&gt;flag&lt;/code&gt; 受限时不可 Interface()）。&lt;/li&gt;
&lt;li&gt;原则：&lt;strong&gt;反射只是&amp;quot;绕到类型系统后面看一眼&amp;quot;，看完一定要回到具体类型继续干活&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="33-对-struct-字段遍历与-tag-读取json-的底层原理"&gt;3.3 对 struct 字段遍历与 tag 读取（json 的底层原理）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dumpStruct&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;any&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reflect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ValueOf&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Type&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;类型: %s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &amp;lt; &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NumField&lt;/span&gt;(); &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;field&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;t&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Field&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// reflect.StructField&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;val&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Field&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// reflect.Value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;tag&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;field&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Tag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;json&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 读 tag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34; 字段 %s kind=%v 值=%v tag=%q\n&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;field&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;field&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Type&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Kind&lt;/span&gt;(), &lt;span style="color:#a6e22e"&gt;val&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Interface&lt;/span&gt;(), &lt;span style="color:#a6e22e"&gt;tag&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;dumpStruct&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;张三&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 输出：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 类型: main.Person&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 字段 Name kind=string 值=张三 tag=&amp;#34;name&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 字段 Age kind=int 值=22 tag=&amp;#34;age&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;这就是 &lt;code&gt;encoding/json&lt;/code&gt; 的底层机制&lt;/strong&gt;：遍历 struct 字段 → 看 &lt;code&gt;json:&amp;quot;xxx&amp;quot;&lt;/code&gt; tag 决定键名/跳过 → 按字段类型编码/解码。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StructTag.Get(&amp;quot;json&amp;quot;)&lt;/code&gt; 可以返回 &lt;code&gt;name,omitempty&lt;/code&gt; 这样的组合串（&lt;code&gt;Lookup&lt;/code&gt; 可区分&amp;quot;有但空&amp;quot;和&amp;quot;没有&amp;quot;）。&lt;/li&gt;
&lt;li&gt;字段可以是导出（大写）或未导出（小写）；未导出字段反射读值会 panic，写值 &lt;code&gt;CanSet=false&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="34-可设置性canset与修改值"&gt;3.4 可设置性（CanSet）与修改值&lt;/h3&gt;
&lt;p&gt;反射改值前提：&lt;strong&gt;值必须是可以寻址的（addressable）&lt;/strong&gt;。&lt;code&gt;reflect.ValueOf(p)&lt;/code&gt; 拿到的是拷贝的 p——改它改不到原对象。&lt;/p&gt;</description></item><item><title>泛型 generics</title><link>https://www.sylgalaxy.xyz/posts/go-02-03-generics/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-02-03-generics/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 template 到 Go 1.18+ 的类型参数：更克制的泛型设计&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 1.18 正式引入泛型（类型参数 Type Parameters）。与 C++ 模板相比，Go 泛型&lt;strong&gt;刻意保持简单&lt;/strong&gt;：没有特化、偏特化、模板元编程、运算符重载，只有&amp;quot;类型参数 + 约束（constraint）&amp;ldquo;两个核心概念。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go 泛型的定位是&lt;strong&gt;解决&amp;quot;写一遍、多个类型用&amp;quot;的容器与工具函数问题&lt;/strong&gt;，不是用来做编译期计算的。能用接口解决的场景，优先接口；泛型是接口的补充而非替代。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func F[T any](...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 用 &lt;code&gt;[T]&lt;/code&gt; 方括号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型约束&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::is_integral_v&amp;lt;T&amp;gt;&lt;/code&gt; / requires&lt;/td&gt;
&lt;td&gt;&lt;code&gt;T int | float64&lt;/code&gt; 或 &lt;code&gt;constraints.Ordered&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 用类型集（union）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;特化&lt;/td&gt;
&lt;td&gt;&lt;code&gt;template&amp;lt;&amp;gt; struct X&amp;lt;int&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;Go 没有特化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;偏特化&lt;/td&gt;
&lt;td&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt; struct X&amp;lt;T*&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ 不支持&lt;/td&gt;
&lt;td&gt;Go 没有偏特化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;默认参数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;template &amp;lt;typename T = int&amp;gt;&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;/td&gt;
&lt;td&gt;&lt;code&gt;std::vector&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;type Vec[T any] []T&lt;/code&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;code&gt;T max(T a, T b)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func Max[T constraints.Ordered](a, b T) T&lt;/code&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;模板元编程 / constexpr&lt;/td&gt;
&lt;td&gt;❌ 无&lt;/td&gt;
&lt;td&gt;Go 泛型是运行时类型，非代码生成&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;td&gt;泛型内不能直接用 &lt;code&gt;+&lt;/code&gt; 除非约束允许&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三泛型函数"&gt;三、泛型函数&lt;/h2&gt;
&lt;h3 id="31-基本语法"&gt;3.1 基本语法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// [T any] 声明类型参数；T 在参数和返回值中可用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Min&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;T&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;any&lt;/span&gt;](&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;T&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;T&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ❌ 编译错误：any 没有约束，不能比较大小&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// if a &amp;lt; b { return a }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;code&gt;any&lt;/code&gt; 意味着&amp;quot;任意类型&amp;rdquo;，编译器不知道 &lt;code&gt;T&lt;/code&gt; 是否支持 &lt;code&gt;&amp;lt;&lt;/code&gt;。必须用&lt;strong&gt;约束&lt;/strong&gt;声明&amp;quot;T 是支持比较的有序类型&amp;quot;：&lt;/p&gt;</description></item><item><title>复合类型</title><link>https://www.sylgalaxy.xyz/posts/go-extra-03/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-03/</guid><description>&lt;blockquote&gt;
&lt;p&gt;数组、切片、Map、结构体——Go 的复合数据结构&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一数组array"&gt;一、数组（Array）&lt;/h2&gt;
&lt;p&gt;Go 的数组是&lt;strong&gt;固定长度、同类型&lt;/strong&gt;的值类型。&lt;/p&gt;
&lt;h3 id="11-声明与初始化"&gt;1.1 声明与初始化&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 声明：长度是类型的一部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;arr&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#75715e"&gt;// [0 0 0 0 0]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;arr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;arr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#f92672"&gt;...&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;} &lt;span style="color:#75715e"&gt;// 编译器自动推断长度 = 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 指定索引初始化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;arr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;} &lt;span style="color:#75715e"&gt;// [0 10 0 30 0]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-数组特点"&gt;1.2 数组特点&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 长度是类型的一部分&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; = [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; = [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// a == b ✅ 同类型、同长度、同元素 → 相等&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; = [&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// a == c ❌ 编译错误：类型不同（[3]int != [4]int）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 值类型：赋值和传参会复制整个数组&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;arr1&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;arr2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;arr1&lt;/span&gt; &lt;span style="color:#75715e"&gt;// arr2 是 arr1 的完整副本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;arr2&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 不影响 arr1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;arr1&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [1 2 3]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ⚠️ 实际开发中很少直接用数组，切片（slice）更常用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-多维数组"&gt;1.3 多维数组&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;matrix&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;][&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;matrix&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;][&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]) &lt;span style="color:#75715e"&gt;// 6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="二切片slice-最核心的数据结构"&gt;二、切片（Slice）— 最核心的数据结构&lt;/h2&gt;
&lt;p&gt;切片是 Go 中&lt;strong&gt;最常用&lt;/strong&gt;的复合类型。它是一个&lt;strong&gt;对底层数组的引用&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>构建部署与 Docker 化</title><link>https://www.sylgalaxy.xyz/posts/go-04-05-docker/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-05-docker/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的动态库/libtool 部署噩梦到 Go 的静态二进制：一个文件搞定容器化&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 编译产出&lt;strong&gt;静态二进制&lt;/strong&gt;（前提下 &lt;code&gt;CGO_ENABLED=0&lt;/code&gt;），没有动态库依赖、没有运行时安装（对比 C++ 的 &lt;code&gt;.so&lt;/code&gt;/&lt;code&gt;.dll&lt;/code&gt; + 运行时动态链接）。这让部署模型极简：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;go build&lt;/code&gt; → 一个可执行文件&lt;/li&gt;
&lt;li&gt;多阶段 Dockerfile（&lt;strong&gt;builder 编译 → 肥镜像剥离 → 瘦镜像运行&lt;/strong&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scratch&lt;/code&gt;/&lt;code&gt;alpine&lt;/code&gt; 镜像，体积通常 &lt;strong&gt;10~30MB&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker run&lt;/code&gt; / Compose 编排&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;C++ 部署的经典烦恼——&lt;code&gt;libstdc++.so.6 not found&lt;/code&gt;、&lt;code&gt;GLIBC_2.34 not found&lt;/code&gt;、ldconfig、需要把一堆 &lt;code&gt;.so&lt;/code&gt; 一起拷走——在纯 Go 世界里直接消失。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：静态编译 + 多阶段构建演示了 Go 的部署哲学：「&lt;strong&gt;产物单一、环境无关&lt;/strong&gt;」。只要你控制好 CGO 开关，一个二进制能跑在任意 Linux 上。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;动态库/静态库 + 可执行文件&lt;/td&gt;
&lt;td&gt;单一可执行文件&lt;/td&gt;
&lt;td&gt;无 &lt;code&gt;.so&lt;/code&gt;/&lt;code&gt;.a&lt;/code&gt; 需分发&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;运行时依赖&lt;/td&gt;
&lt;td&gt;目标机需匹配 libc/动态库&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CGO_ENABLED=0&lt;/code&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;code&gt;GLIBC_2.30 not found&lt;/code&gt;、&lt;code&gt;.so&lt;/code&gt; 名冲突&lt;/td&gt;
&lt;td&gt;无（Go 自带运行时）&lt;/td&gt;
&lt;td&gt;彻底告别 ABI 地狱&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;镜像方案&lt;/td&gt;
&lt;td&gt;手动装依赖/多级 COPY .so&lt;/td&gt;
&lt;td&gt;多阶段：build → scratch/alpine&lt;/td&gt;
&lt;td&gt;一条 &lt;code&gt;FROM ... AS builder&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;镜像体积&lt;/td&gt;
&lt;td&gt;常见 500MB~2GB&lt;/td&gt;
&lt;td&gt;常见 10~30MB&lt;/td&gt;
&lt;td&gt;静态二进制省掉一层层库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基础镜像&lt;/td&gt;
&lt;td&gt;ubuntu/debian 全量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;scratch&lt;/code&gt;（空镜像）/ &lt;code&gt;alpine&lt;/code&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;code&gt;HEALTHCHECK&lt;/code&gt; + HTTP /healthz&lt;/td&gt;
&lt;td&gt;Dockerfile 指令&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;服务发现/编排&lt;/td&gt;
&lt;td&gt;systemd / 手动进程管理&lt;/td&gt;
&lt;td&gt;同样 systemd，但容器内单进程&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;td&gt;镜像即交付物&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-go-build-产物静态优先"&gt;3.1 go build 产物：静态优先&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 常见部署编译命令（Linux amd64、静态、精简符号）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CGO_ENABLED&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; GOOS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;linux GOARCH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;amd64 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go build -ldflags &lt;span style="color:#e6db74"&gt;&amp;#34;-s -w&amp;#34;&lt;/span&gt; -o app ./cmd/server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 产物检查（Linux 上）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;file app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app: ELF 64-bit LSB executable, x86-64, statically linked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 确认没有动态链接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ldd app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 不是 a dynamic executable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;C++ 对照&lt;/strong&gt;：C++ 默认生成动态链接可执行文件，目标机必须带好 &lt;code&gt;.so&lt;/code&gt; 与匹配的 libc 版本；Go 默认（cgo 关）就是&lt;strong&gt;静态链接&lt;/strong&gt;。代价与取舍见 3.3。&lt;/p&gt;</description></item><item><title>函数、多返回值与闭包</title><link>https://www.sylgalaxy.xyz/posts/go-01-06/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-06/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 函数的设计哲学：多返回值、闭包、defer——简洁而强大&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一函数定义"&gt;一、函数定义&lt;/h2&gt;
&lt;h3 id="11-基本语法"&gt;1.1 基本语法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 格式：func 函数名(参数名 类型, ...) 返回类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;C++ 对照：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;code&gt;int add(int a, int b)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func add(a int, b int) int&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型位置&lt;/td&gt;
&lt;td&gt;类型在前 &lt;code&gt;int a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;类型在后 &lt;code&gt;a int&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多返回值&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::pair&amp;lt;T1,T2&amp;gt;&lt;/code&gt; / &lt;code&gt;std::tuple&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;直接返回 &lt;code&gt;(int, string)&lt;/code&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;h3 id="12-参数类型简写"&gt;1.2 参数类型简写&lt;/h3&gt;
&lt;p&gt;相邻同类型参数可以合并：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 两种写法等价&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calc&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; { &lt;span style="color:#f92672"&gt;...&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calc&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; { &lt;span style="color:#f92672"&gt;...&lt;/span&gt; } &lt;span style="color:#75715e"&gt;// 更简洁&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-没有默认参数没有函数重载"&gt;1.3 没有默认参数，没有函数重载&lt;/h3&gt;
&lt;p&gt;Go &lt;strong&gt;不支持&lt;/strong&gt;默认参数和函数重载。需要类似效果时用函数选项模式或可变参数：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 用 Option 模式替代默认参数（后面会详细讲）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerOption&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Addr&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Port&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 或者更简单的做法：拆成多个函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NewServer&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;addr&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Server&lt;/span&gt; { &lt;span style="color:#f92672"&gt;...&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NewServerWithPort&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;addr&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;port&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Server&lt;/span&gt; { &lt;span style="color:#f92672"&gt;...&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="二多返回值"&gt;二、多返回值&lt;/h2&gt;
&lt;p&gt;这是 Go 最核心的设计之一，C++ 没有直接对应。&lt;/p&gt;</description></item><item><title>函数与方法</title><link>https://www.sylgalaxy.xyz/posts/go-extra-06/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-06/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的函数设计、方法接收者、闭包与高阶函数&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一函数基础"&gt;一、函数基础&lt;/h2&gt;
&lt;h3 id="11-函数定义"&gt;1.1 函数定义&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 基本语法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;函数名&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;参数列表&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;返回类型&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 函数体&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 多参数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 相同类型可以合并参数名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 多返回值（Go 的核心特性之一）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;divide&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;) (&lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;division by zero&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用多返回值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;divide&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 3.3333333333333335&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-命名返回值"&gt;1.2 命名返回值&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 返回值可以有名字，相当于在函数内部声明了局部变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;split&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) (&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 裸 return，自动返回 x, y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 命名返回值 + 裸 return 在短函数中可读性好&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 但长函数中容易出错，建议谨慎使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-可变参数函数variadic"&gt;1.3 可变参数函数（Variadic）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用 ... 实现可变参数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;total&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;total&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;total&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 传递切片给可变参数：使用 ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;sum&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt;&lt;span style="color:#f92672"&gt;...&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="二函数作为值"&gt;二、函数作为值&lt;/h2&gt;
&lt;h3 id="21-函数是一等公民"&gt;2.1 函数是一等公民&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 函数可以赋值给变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 函数可以作为参数传递&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;apply&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;op&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;op&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;apply&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 函数可以作为返回值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;makeMultiplier&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;factor&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;factor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;double&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;makeMultiplier&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;double&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="三闭包closure"&gt;三、闭包（Closure）&lt;/h2&gt;
&lt;p&gt;闭包是&lt;strong&gt;引用了外部变量的匿名函数&lt;/strong&gt;。Go 中每次创建闭包都会捕获变量的引用。&lt;/p&gt;</description></item><item><title>环境与工具链</title><link>https://www.sylgalaxy.xyz/posts/go-01-01/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-01/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的安装、配置与核心工具链速览&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一go-的安装与配置"&gt;一、Go 的安装与配置&lt;/h2&gt;
&lt;h3 id="11-下载安装"&gt;1.1 下载安装&lt;/h3&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;Windows&lt;/td&gt;
&lt;td&gt;下载 &lt;code&gt;.msi&lt;/code&gt; 安装包：&lt;a href="https://go.dev/dl/"&gt;go.dev/dl&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;brew install go&lt;/code&gt; 或下载 &lt;code&gt;.pkg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;下载 &lt;code&gt;.tar.gz&lt;/code&gt; 解压至 &lt;code&gt;/usr/local/go&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;安装完成后验证：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go version
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# go version go1.24.x windows/amd64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-环境变量"&gt;1.2 环境变量&lt;/h3&gt;
&lt;p&gt;Go 通过几个关键环境变量控制行为：&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;th&gt;常用值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GOROOT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 安装目录（一般自动检测）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/usr/local/go&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GOPATH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;工作区目录（存放模块缓存和编译缓存）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/go&lt;/code&gt;（默认）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GOBIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go install&lt;/code&gt; 安装的可执行文件目录&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$GOPATH/bin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GOPROXY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;模块代理地址（国内必改）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://goproxy.cn,direct&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GO111MODULE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;模块模式开关（1.16+ 默认开启）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;on&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;国内加速配置&lt;/strong&gt;（重要）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 永久生效（PowerShell）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go env -w GOPROXY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;https://goproxy.cn,direct
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 或设置环境变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set GOPROXY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;https://goproxy.cn,direct
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="13-工作区结构gopath"&gt;1.3 工作区结构（GOPATH）&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;GOPATH/
├── bin/ # go install 编译出的可执行文件
├── pkg/ # 编译缓存
└── src/ # [已废弃] 早期放源码，现在用 Go Modules
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Go 1.16+ 不再需要把代码放在 &lt;code&gt;GOPATH/src&lt;/code&gt; 下&lt;/strong&gt;。使用 Go Modules 后，项目可以放在任意目录。&lt;/p&gt;</description></item><item><title>接口 interface</title><link>https://www.sylgalaxy.xyz/posts/go-02-01-interface/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-02-01-interface/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的虚函数/抽象类到 Go 的接口：鸭子类型、隐式实现与组合式设计&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 的 &lt;code&gt;interface&lt;/code&gt; 是一组&lt;strong&gt;方法签名&lt;/strong&gt;的集合，它定义了类型&amp;quot;能做什么&amp;quot;，而不是&amp;quot;是什么&amp;quot;。与 C++ 的抽象类最大的不同：Go 接口是&lt;strong&gt;隐式实现&lt;/strong&gt;——一个类型只要实现了接口里的所有方法，就自动满足该接口，&lt;strong&gt;不需要显式声明&lt;/strong&gt; &lt;code&gt;implements&lt;/code&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go 接口让&amp;quot;面向接口编程&amp;quot;从设计原则变成了语言级强制。它催生了组合优于继承、依赖注入、mock 测试等一整套惯用法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;class Shape { virtual double area() = 0; }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;type Shape interface { Area() float64 }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 只有方法签名，没有数据成员&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;实现&lt;/td&gt;
&lt;td&gt;&lt;code&gt;class Circle : public Shape { ... }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func (c Circle) Area() float64 { ... }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;隐式实现&lt;/strong&gt;，无需继承声明&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多态&lt;/td&gt;
&lt;td&gt;虚函数表 vtable + 指针/引用&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;code&gt;void*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;interface{}&lt;/code&gt; / &lt;code&gt;any&lt;/code&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;td&gt;无菱形问题&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型断言&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dynamic_cast&amp;lt;T*&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;v, ok := x.(T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 更安全：带 ok 判断&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;判断实现&lt;/td&gt;
&lt;td&gt;&lt;code&gt;typeid&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;hr&gt;
&lt;h2 id="三接口的定义与实现"&gt;三、接口的定义与实现&lt;/h2&gt;
&lt;h3 id="31-定义接口"&gt;3.1 定义接口&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 定义接口：只声明方法，不实现&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Shape&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Perimeter&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-隐式实现"&gt;3.2 隐式实现&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Circle 不需要写 &amp;#34;implements Shape&amp;#34;，只要方法对上就自动满足&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Circle&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Radius&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Circle&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.14159&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Radius&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Radius&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Circle&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Perimeter&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.14159&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Radius&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Rectangle 同样自动实现 Shape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Perimeter&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="33-使用接口"&gt;3.3 使用接口&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;printShape&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Shape&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;面积=%.2f, 周长=%.2f\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;(), &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Perimeter&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Circle&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Radius&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printShape&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 传入接口参数，自动多态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printShape&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 接口变量可以存任意实现类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Shape&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;对照 C++&lt;/strong&gt;：C++ 必须 &lt;code&gt;class Circle : public Shape&lt;/code&gt; 显式继承；Go 只要方法签名对上就行，&lt;strong&gt;实现与接口完全解耦&lt;/strong&gt;——甚至可以给别人的类型补上方法让它满足你的接口。&lt;/p&gt;</description></item><item><title>接口与多态</title><link>https://www.sylgalaxy.xyz/posts/go-extra-07/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-07/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的隐式接口、空接口与面向接口编程&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一接口基础"&gt;一、接口基础&lt;/h2&gt;
&lt;h3 id="11-接口定义"&gt;1.1 接口定义&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 接口是一组方法签名的集合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Reader&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Read&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) (&lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Writer&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Write&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) (&lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 组合多个接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReadWriter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Reader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Writer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-隐式实现鸭子类型"&gt;1.2 隐式实现（鸭子类型）&lt;/h3&gt;
&lt;p&gt;Go 的接口是&lt;strong&gt;隐式实现&lt;/strong&gt;的——不需要 &lt;code&gt;implements&lt;/code&gt; 关键字：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 只要一个类型实现了接口的所有方法，它就自动满足该接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyReader&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;pos&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;MyReader&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Read&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) (&lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 实现 Read 方法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;pos&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;io&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt; = copy(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;pos&lt;/span&gt;:])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;pos&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// MyReader 自动实现了 io.Reader 接口，无需声明&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;io&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Reader&lt;/span&gt; = &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;MyReader&lt;/span&gt;{} &lt;span style="color:#75715e"&gt;// ✅ 编译通过&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Go 的哲学：行为决定类型，而不是声明决定类型。&lt;/strong&gt; 如果它像鸭子一样走路、像鸭子一样叫，那它就是鸭子。&lt;/p&gt;</description></item><item><title>结构体与方法</title><link>https://www.sylgalaxy.xyz/posts/go-01-07/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-07/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 没有 class，结构体(struct) + 方法(method) 是面向对象的核心替代方案&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一c-对照速查表"&gt;一、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;C++ 概念&lt;/th&gt;
&lt;th&gt;Go 对应&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;struct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;struct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;默认 public，字段首字母大写才导出&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;class&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;struct&lt;/code&gt; + 方法&lt;/td&gt;
&lt;td&gt;Go 没有 class 关键字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;this&lt;/code&gt; 指针&lt;/td&gt;
&lt;td&gt;Receiver（值/指针）&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;code&gt;NewXxx()&lt;/code&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;code&gt;defer&lt;/code&gt; + &lt;code&gt;Close()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;没有析构函数语法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;继承 (&lt;code&gt;is-a&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;嵌入 (&lt;code&gt;has-a&lt;/code&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;Go 刻意不提供&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;访问控制 &lt;code&gt;private/protected/public&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;/td&gt;
&lt;td&gt;泛型（Go 1.18+）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func F[T any](x T) T&lt;/code&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;鸭子类型，无需声明 implements&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="二结构体定义与零值"&gt;二、结构体定义与零值&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 定义结构体：type + struct 关键字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// C++ 对比：类似 struct MyPoint { double x; double y; }; 但没有方法体&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Point&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;X&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 首字母大写 = 导出字段（其他包可访问）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Y&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 首字母小写 = 未导出（仅本包内可访问）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 零值：所有字段自动初始化为各自类型的零值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// float64 -&amp;gt; 0.0, int -&amp;gt; 0, string -&amp;gt; &amp;#34;&amp;#34;, bool -&amp;gt; false, 指针/切片/map -&amp;gt; nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Point&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;零值: %+v\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// {X:0 Y:0 name:}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="三结构体初始化"&gt;三、结构体初始化&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Email&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式1: 字面量（最常用，推荐）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;u1&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;张三&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Email&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;zhangsan@example.com&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式2: 按字段名初始化（部分字段，其余为零值）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;u2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;李四&amp;#34;&lt;/span&gt;} &lt;span style="color:#75715e"&gt;// Age=0, Email=&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式3: 按顺序初始化（不推荐！字段顺序变化会导致 bug）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;u3&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;王五&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;wangwu@example.com&amp;#34;&lt;/span&gt;} &lt;span style="color:#75715e"&gt;// 需要 import fmt 不会用到，编译器不检查字段名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式4: new 返回指针，所有字段为零值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;u4&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; new(&lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// *User 类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;u4&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;赵六&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Go 允许对指针直接访问字段，自动解引用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u4&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式5: 声明后再赋值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;u5&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;u5&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;钱七&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;u5&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;u5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="newxxx-工厂函数替代构造函数"&gt;NewXxx 工厂函数（替代构造函数）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Go 没有构造函数，惯用 NewXxx 工厂函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NewUser&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;email&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;User&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Email&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;email&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// u := NewUser(&amp;#34;张三&amp;#34;, &amp;#34;zhangsan@example.com&amp;#34;, 25)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 优点：返回指针，避免大结构体拷贝；可以做参数校验&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="四结构体比较"&gt;四、结构体比较&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Point&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;X&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Y&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Point&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Point&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Point&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 同类型结构体可以用 == 比较（逐字段比较）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 包含不可比较字段（slice, map）的结构体不能用 ==&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// type Bad struct { Data []int }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// var x, y Bad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// x == y // 编译错误！slice 不能比较&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="五方法定义"&gt;五、方法定义&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 值 Receiver：操作的是副本，不会修改原值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// C++ 对比：相当于 void method() const（不能修改成员）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 指针 Receiver：操作的是原值，可以修改字段&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// C++ 对比：相当于非 const 的 this 指针方法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;SetWidth&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;w&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;w&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 直接修改原结构体&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// String 方法实现 fmt.Stringer 接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Rectangle(%.1f x %.1f)&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rect&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;rect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// 12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;SetWidth&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;rect&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// Rectangle(5.0 x 4.0)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Go 会自动处理取地址/解引用：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rectPtr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rectPtr&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// 值方法：自动解引用 (*rectPtr).Area()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;rectPtr&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;Area&lt;/span&gt;() &lt;span style="color:#75715e"&gt;// 手动解引用，效果相同&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rect2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Rectangle&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Width&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Height&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;rect2&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;SetWidth&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 指针方法：自动取地址 (&amp;amp;rect2).SetWidth(3)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="六值-receiver-vs-指针-receiver"&gt;六、值 Receiver vs 指针 Receiver&lt;/h2&gt;
&lt;h3 id="选择原则"&gt;选择原则&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;场景&lt;/th&gt;
&lt;th&gt;推荐 Receiver&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;/td&gt;
&lt;td&gt;值 Receiver&lt;/td&gt;
&lt;td&gt;避免不必要的拷贝开销（小结构体）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;需要修改字段&lt;/td&gt;
&lt;td&gt;指针 Receiver&lt;/td&gt;
&lt;td&gt;必须修改原值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;结构体较大&lt;/td&gt;
&lt;td&gt;指针 Receiver&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;slice/map 字段需修改&lt;/td&gt;
&lt;td&gt;指针 Receiver&lt;/td&gt;
&lt;td&gt;虽然 slice 底层是引用，但语义更清晰&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="关键区别"&gt;关键区别&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Counter&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 值 Receiver：操作的是拷贝&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Counter&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;IncByValue&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 修改的是副本，原值不变！&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 指针 Receiver：操作的是原值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Counter&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;IncByPtr&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 直接修改原值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Counter&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;IncByValue&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 0 —— 没变！&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;IncByPtr&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Value&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 1 —— 变了&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="七结构体嵌入embedding-组合优于继承"&gt;七、结构体嵌入（Embedding）—— 组合优于继承&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 基础结构体&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 嵌入 Person —— 注意：没有字段名！&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 这不是 &amp;#34;Person 字段&amp;#34;，而是把 Person 的字段和方法&amp;#34;提升&amp;#34;到 Employee 中&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Employee&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 嵌入（embedding），不是字段&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Company&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Salary&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Person 的方法也会被提升&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Greet&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;你好，我是 %s&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Employee 自己的方法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;e&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Employee&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Info&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s 在 %s 工作，薪资 %.0f&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Company&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;e&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Salary&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化：嵌入结构体可以逐层初始化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;emp&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Employee&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;张三&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Company&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;字节跳动&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Salary&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 字段提升：直接访问嵌入结构体的字段&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;emp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;张三&amp;#34; —— Person 的字段被提升&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;emp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;emp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Company&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;字节跳动&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方法也被提升&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;emp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Greet&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// &amp;#34;你好，我是 张三&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 也可以显式指定&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;emp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;张三&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="嵌入接口"&gt;嵌入接口&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 结构体可以嵌入接口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Logger&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Server&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Logger&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 嵌入接口：Server 隐式实现了 Logger&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Addr&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 使用时 Server 必须给 Logger 赋值，否则调用 Log 会 panic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// srv := Server{Logger: someLoggerImpl, Addr: &amp;#34;:8080&amp;#34;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;C++ 对比：嵌入 vs 继承&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>类型断言与 type-switch</title><link>https://www.sylgalaxy.xyz/posts/go-02-06-type-switch/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-02-06-type-switch/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 dynamic_cast / typeid 到 Go 的类型断言、类型开关与反射初探&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;接口变量在运行时存储了&amp;quot;动态类型&amp;quot;。当我们需要&lt;strong&gt;把接口值还原成具体类型&lt;/strong&gt;、或&lt;strong&gt;按不同类型走不同逻辑&lt;/strong&gt;时，就用类型断言（type assertion）和类型开关（type switch）。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go 类型断言是 &lt;code&gt;x.(T)&lt;/code&gt; 语法——它是&amp;quot;安全的 dynamic_cast&amp;quot;：带 &lt;code&gt;ok&lt;/code&gt; 判断时永远不会 panic。类型开关 &lt;code&gt;switch v := x.(type)&lt;/code&gt; 则是处理&amp;quot;未知类型集合&amp;quot;最优雅的方式。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;dynamic_cast&amp;lt;T*&amp;gt;(ptr)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;v, ok := x.(T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 更简洁，双返回值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;不安全转型&lt;/td&gt;
&lt;td&gt;&lt;code&gt;static_cast&lt;/code&gt; / &lt;code&gt;reinterpret_cast&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;v := x.(T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 会 panic（不推荐）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;类型判断&lt;/td&gt;
&lt;td&gt;&lt;code&gt;typeid(x) == typeid(T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x.(type)&lt;/code&gt;（type switch）&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;code&gt;typeid(x).name()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fmt.Sprintf(&amp;quot;%T&amp;quot;, x)&lt;/code&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;RTTI / &lt;code&gt;&amp;lt;typeinfo&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reflect&lt;/code&gt; 包&lt;/td&gt;
&lt;td&gt;用法差异大&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三类型断言基础"&gt;三、类型断言基础&lt;/h2&gt;
&lt;h3 id="31-语法与两种形式"&gt;3.1 语法与两种形式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;any&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 形式一：带 ok（推荐，安全）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;.(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;是 int:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;不是 int&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 形式二：不带 ok（不推荐，失败直接 panic）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;v2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;.(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// ✅ 成功&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// v3 := x.(string) // ❌ panic: interface conversion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;规则&lt;/strong&gt;：永远用带 &lt;code&gt;ok&lt;/code&gt; 的形式。不带 ok 的写法相当于 C++ 的 &lt;code&gt;static_cast&lt;/code&gt;——假设你知道类型，错了就崩。&lt;/p&gt;</description></item><item><title>流程控制</title><link>https://www.sylgalaxy.xyz/posts/go-extra-04/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-extra-04/</guid><description>&lt;blockquote&gt;
&lt;p&gt;if、for、switch、defer——Go 的控制流语句&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一if-条件语句"&gt;一、if 条件语句&lt;/h2&gt;
&lt;h3 id="11-基本语法"&gt;1.1 基本语法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Go 的 if 条件不需要括号，但花括号必须存在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;score&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;pass&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;score&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;good&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;fail&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-if-带初始化语句"&gt;1.2 if 带初始化语句&lt;/h3&gt;
&lt;p&gt;Go 的 &lt;code&gt;if&lt;/code&gt; 可以包含一条&lt;strong&gt;简短的初始化语句&lt;/strong&gt;，变量作用域仅限于 if/else 块内：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 经典用法：同时获取值和错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;doSomething&lt;/span&gt;(); &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;error:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 这里 err 不可用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 读取文件的经典模式&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadFile&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;config.txt&amp;#34;&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;读取失败:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;内容:&amp;#34;&lt;/span&gt;, string(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Go 的惯例&lt;/strong&gt;：&lt;code&gt;if err != nil&lt;/code&gt; 是 Go 代码中出现频率最高的模式之一。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二for-循环"&gt;二、for 循环&lt;/h2&gt;
&lt;p&gt;Go &lt;strong&gt;只有 for 一种循环语句&lt;/strong&gt;，但功能覆盖了 while、do-while 的场景。&lt;/p&gt;
&lt;h3 id="21-三种形式"&gt;2.1 三种形式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 形式1：传统 for 循环&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &amp;lt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 形式2：while 风格（只有条件）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;condition&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 形式3：无限循环&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// break 退出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;done&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="22-遍历集合"&gt;2.2 遍历集合&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 遍历切片/数组&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;索引=%d 值=%d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 只要值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 只要索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 遍历 map&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Java&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s → %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 遍历字符串（按 rune 遍历）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ch&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Hello, 世界&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;字节位置=%d 字符=%c Unicode=%U\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ch&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ch&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 输出中 &amp;#39;世&amp;#39; 的索引是 7（不是 10），因为 range 按 rune 遍历&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="23-for-range-陷阱"&gt;2.3 for-range 陷阱&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 陷阱：range 的值是副本，修改不影响原切片&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#75715e"&gt;// ❌ 只修改了副本，nums 不变&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 正确做法：通过索引修改&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;] = &lt;span style="color:#a6e22e"&gt;nums&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#75715e"&gt;// ✅ 修改原切片&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="三switch-多分支"&gt;三、switch 多分支&lt;/h2&gt;
&lt;p&gt;Go 的 &lt;code&gt;switch&lt;/code&gt; 比其他语言更强大，默认不穿透（fall through）。&lt;/p&gt;</description></item><item><title>流程控制: if, for, switch</title><link>https://www.sylgalaxy.xyz/posts/go-01-03-if-for-switch/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-03-if-for-switch/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的流程控制关键字精简而强大——没有 &lt;code&gt;while&lt;/code&gt;、没有 &lt;code&gt;do&lt;/code&gt;、&lt;code&gt;switch&lt;/code&gt; 默认不穿透&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一c-对照速查表"&gt;一、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;if (cond) {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;if cond {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 不需要括号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;初始化语句&lt;/td&gt;
&lt;td&gt;&lt;code&gt;if (int x = f(); x &amp;gt; 0)&lt;/code&gt; (C++17)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;if x := f(); x &amp;gt; 0&lt;/code&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;code&gt;for (init; cond; post) {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for init; cond; post {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 统一用 &lt;code&gt;for&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;while 循环&lt;/td&gt;
&lt;td&gt;&lt;code&gt;while (cond) {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for cond {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 无 &lt;code&gt;while&lt;/code&gt; 关键字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;do-while&lt;/td&gt;
&lt;td&gt;&lt;code&gt;do {} while (cond);&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for { ...; if !cond { break } }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 无 &lt;code&gt;do-while&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;无限循环&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for (;;) {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 写法更简洁&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;范围遍历&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for (auto&amp;amp; x : vec) {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for i, v := range slice {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;range&lt;/code&gt; 可解构 key/value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;switch 穿透&lt;/td&gt;
&lt;td&gt;默认穿透（需 &lt;code&gt;break&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;默认不穿透（需 &lt;code&gt;fallthrough&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;完全相反&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;switch 无条件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;switch { case ...: }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;switch { case ...: }&lt;/code&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;code&gt;dynamic_cast&lt;/code&gt;/&lt;code&gt;typeid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;switch v := x.(type)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 的 type switch 更优雅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;延迟执行&lt;/td&gt;
&lt;td&gt;RAII / 析构函数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defer&lt;/code&gt; 是函数级，非作用域级&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;goto&lt;/td&gt;
&lt;td&gt;&lt;code&gt;goto label;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;goto label;&lt;/code&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;code&gt;break label&lt;/code&gt;（跳出循环）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;break label&lt;/code&gt;（跳出标签所在的 for）&lt;/td&gt;
&lt;td&gt;Go 标签只对 &lt;code&gt;for&lt;/code&gt; 有效&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="二if-语句"&gt;二、if 语句&lt;/h2&gt;
&lt;h3 id="21-基本用法不需要括号"&gt;2.1 基本用法——不需要括号&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Go: 条件表达式不需要括号&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &amp;gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;正数&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;零&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;负数&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;C++ 对照：&lt;code&gt;if (x &amp;gt; 0) { ... }&lt;/code&gt; — Go 省略了括号，且 &lt;code&gt;{&lt;/code&gt; 不能另起一行（编译器自动插入分号机制）。&lt;/p&gt;</description></item><item><title>三色 GC 与写屏障</title><link>https://www.sylgalaxy.xyz/posts/go-06-03-gc/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-06-03-gc/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 的 RAII/智能指针是&amp;quot;代码到哪回收到哪&amp;quot;；Go 的 GC 让事情自动发生——代价是你必须理解它何时跑、怎么跑&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 从 1.5 开始使用&lt;strong&gt;并发三色标记-清除&lt;/strong&gt;垃圾回收器：标记阶段与应用并发跑，通过&lt;strong&gt;写屏障&lt;/strong&gt;保证并发下的正确性，把 STW（Stop-The-World，全停）压缩到毫秒级。本章剖析三色算法、写屏障原理、&lt;code&gt;GC 触发时机（GOGC / GOMEMLIMIT）&lt;/code&gt;、&lt;code&gt;gctrace&lt;/code&gt; 日志解读，以及从 C++ 视角看&amp;quot;自动回收&amp;quot;带来的确定性问题。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：垃圾回收的本质是&amp;quot;追踪所有存活对象的引用图&amp;quot;。三色让追踪与程序运行并发，写屏障保证并发期间引用关系不变而漏标对象；&lt;code&gt;GOGC==100&lt;/code&gt; 的意思是&amp;quot;堆翻倍时才触发下一次 GC&amp;quot;。理解这些，你才能在调优时不被玄学推着走。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;new&lt;/code&gt;/&lt;code&gt;delete&lt;/code&gt;、RAII、&lt;code&gt;shared_ptr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;自动 GC&lt;/td&gt;
&lt;td&gt;C++ 确定、Go 不确定（回收时点不定）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;引用计数&lt;/td&gt;
&lt;td&gt;手写计数 / &lt;code&gt;shared_ptr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;无引用计数&lt;/td&gt;
&lt;td&gt;Go 用可达性分析，无循环引用问题&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;循环引用&lt;/td&gt;
&lt;td&gt;&lt;code&gt;weak_ptr&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;/td&gt;
&lt;td&gt;&lt;code&gt;shared_ptr&lt;/code&gt; 防悬垂、&lt;code&gt;weak_ptr&lt;/code&gt; 观测&lt;/td&gt;
&lt;td&gt;不可能悬垂（GC 保证活着就安全）&lt;/td&gt;
&lt;td&gt;但 &lt;code&gt;unsafe&lt;/code&gt; 除外&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;析构时机&lt;/td&gt;
&lt;td&gt;作用域结束/&lt;code&gt;shared_ptr&lt;/code&gt; 归零&lt;/td&gt;
&lt;td&gt;不确定（对象 GC 后才回收内存）&lt;/td&gt;
&lt;td&gt;需要清理副作用时必须显式 &lt;code&gt;Close&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;手动释放&lt;/td&gt;
&lt;td&gt;&lt;code&gt;delete&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;*不存在（&lt;code&gt;runtime.GC()&lt;/code&gt; 只建议回收）&lt;/td&gt;
&lt;td&gt;别依赖手工 GC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;触发条件&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;heap 增长到阈值 / 周期 / 显式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOGC&lt;/code&gt;、&lt;code&gt;GOMEMLIMIT&lt;/code&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;少量 STW（毫秒级）&lt;/td&gt;
&lt;td&gt;现在基本无感，但被 K8s CPU 限流仍可能抖动&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;td&gt;追求低延迟要控制分配率&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-为什么要-gc先看可达性"&gt;3.1 为什么要 GC：先看可达性&lt;/h3&gt;
&lt;p&gt;GC 不关心&amp;quot;这块内存是不是有人 stack 上引用&amp;quot;的细节，只关心一件事：&lt;strong&gt;从根（root）出发，你能走到哪些对象？&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>数据竞争与 race 检测</title><link>https://www.sylgalaxy.xyz/posts/go-03-08-race/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-03-08-race/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 的 TSan / helgrind 你在用，Go 内置了一个更好使的：&lt;code&gt;go run -race&lt;/code&gt; 一键找数据竞争&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;数据竞争（data race）&lt;/strong&gt;：两个或多个 goroutine &lt;strong&gt;并发访问同一内存位置&lt;/strong&gt;，且&lt;strong&gt;至少一个是写操作&lt;/strong&gt;，且没有任何同步（锁 / channel / 原子操作）约束它们之间的顺序。数据竞争的结果是&lt;strong&gt;未定义行为&lt;/strong&gt;（UB）：读到撕裂值、编译器优化后行为诡异、crash、或者——最恼人的——&lt;strong&gt;偶尔才出错&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;C++ 里你熟知的工具：&lt;strong&gt;ThreadSanitizer（TSan）&lt;/strong&gt;、&lt;code&gt;-fsanitize=thread&lt;/code&gt;、helgrind。Go 的对应物是内置的 &lt;strong&gt;race detector&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go run -race main.go &lt;span style="color:#75715e"&gt;# 直接跑并检测&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go test -race ./... &lt;span style="color:#75715e"&gt;# 测试时检测（推荐）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go build -race main.go &lt;span style="color:#75715e"&gt;# 构建带检测的二进制（性能有损，仅调试）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go race detector 不是「预防工具」，而是「&lt;strong&gt;逮现行犯&lt;/strong&gt;」的探针——它监测每个内存访问，报告「两个 goroutine 同时访问同一地址」的现场。&lt;strong&gt;加了 -race，不等于程序没问题；没加 -race，问题照样存在。&lt;/strong&gt; 修复手段三件套：Mutex、atomic、channel 传值。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;两个线程无同步访问同一地址&lt;/td&gt;
&lt;td&gt;同，goroutine 版&lt;/td&gt;
&lt;td&gt;语义一致：至少一写 + 无同步&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;检测工具&lt;/td&gt;
&lt;td&gt;TSan / &lt;code&gt;-fsanitize=thread&lt;/code&gt; / helgrind&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go run -race&lt;/code&gt; / &lt;code&gt;go test -race&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go &lt;strong&gt;内置&lt;/strong&gt;，零配置，一行参数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;检测原理&lt;/td&gt;
&lt;td&gt;影子内存 + happens-before 分析&lt;/td&gt;
&lt;td&gt;同样基于 happens-before 的 shadow 内存&lt;/td&gt;
&lt;td&gt;实现同源（Go 4 个字节内存配 8 字节影子）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;共享计数器&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::atomic&amp;lt;int&amp;gt;&lt;/code&gt; / mutex&lt;/td&gt;
&lt;td&gt;&lt;code&gt;atomic.AddInt64&lt;/code&gt;（首选）&lt;/td&gt;
&lt;td&gt;Go 原子 / 锁 / channel 三种解法都有&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;map 并发写&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::unordered_map&lt;/code&gt; + mutex&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;map 并发写 = 直接 panic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Go 有额外保护：写中读/写检测&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;修复手段&lt;/td&gt;
&lt;td&gt;锁 / 原子 / 无共享&lt;/td&gt;
&lt;td&gt;Mutex / atomic / channel 传值&lt;/td&gt;
&lt;td&gt;第三种（传值）是 Go 特色&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;内存模型文档&lt;/td&gt;
&lt;td&gt;cppreference memory_order&lt;/td&gt;
&lt;td&gt;&lt;a href="https://go.dev/ref/mem"&gt;The Go Memory Model&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Go 文档短得多，先读「happen-before」&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;检测开销&lt;/td&gt;
&lt;td&gt;慢 5~15 倍&lt;/td&gt;
&lt;td&gt;运行慢 5&lt;del&gt;10 倍，内存多 5&lt;/del&gt;10 倍&lt;/td&gt;
&lt;td&gt;都只该在测试/CI 用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-什么是数据竞争"&gt;3.1 什么是数据竞争&lt;/h3&gt;
&lt;p&gt;判定为数据竞争需要三条同时成立：&lt;/p&gt;</description></item><item><title>数据库接入 database/sql · gorm · sqlx</title><link>https://www.sylgalaxy.xyz/posts/go-05-04-database-sql-gorm-sqlx/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-05-04-database-sql-gorm-sqlx/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 sqlite3 / libpq + 手写 ORM 到 Go：database/sql 抽象层 + 驱动隔离，数据访问可以有一份标准答案&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 数据库世界的中心是 &lt;code&gt;database/sql&lt;/code&gt;——一个&lt;strong&gt;驱动无关的 SQL 访问抽象层&lt;/strong&gt;。就像 C++ 里 &lt;code&gt;sqlite3_open&lt;/code&gt;、&lt;code&gt;PQconnectdb&lt;/code&gt; 各写各的，Go 则约定「先 &lt;code&gt;sql.Open&lt;/code&gt; 拿到抽象连接，然后 Query/Exec/事务全走同一套接口」，不同数据库只是&lt;strong&gt;换一个驱动 import 和连接串&lt;/strong&gt;。sqlx 在其上补了「结构体 ↔ 行」的便捷映射；gorm 则是全功能 ORM（自动建表、关联、迁移），适合快速开发。三者是「底层 → 便捷 → 全自动」的一条谱系。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：先记住 &lt;code&gt;database/sql&lt;/code&gt; 的三个纪律——&lt;strong&gt;连接池要调&lt;/strong&gt;、&lt;strong&gt;行/stmt/tx 用后必关&lt;/strong&gt;、&lt;strong&gt;占位符随驱动变化&lt;/strong&gt;（MySQL 用 &lt;code&gt;?&lt;/code&gt;，PostgreSQL 用 &lt;code&gt;$1&lt;/code&gt;）。在这之上，sqlx 与 gorm 都是锦上添花。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;sqlite3.h / libpq 各一套&lt;/td&gt;
&lt;td&gt;&lt;code&gt;database/sql&lt;/code&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;自己写 thread pool&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sql.DB&lt;/code&gt; 自带 + &lt;code&gt;SetMaxOpenConns&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;连接池是 &lt;code&gt;DB&lt;/code&gt; 的默认行为&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;查询单行&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sqlite3_step&lt;/code&gt; + 手动取列&lt;/td&gt;
&lt;td&gt;&lt;code&gt;db.QueryRow(...).Scan(&amp;amp;v)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Scan 一次到位&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;code&gt;rows.Next()&lt;/code&gt; + &lt;code&gt;rows.Scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;循环+Scan，模板化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;预处理&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sqlite3_prepare_v2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;db.Prepare&lt;/code&gt; + &lt;code&gt;stmt.Exec&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;语义一致，但事务内惯用 tx 级 prepare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;事务&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BEGIN/COMMIT/ROLLBACK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;db.Begin()&lt;/code&gt; + &lt;code&gt;tx.Commit/Rollback&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;要 &lt;code&gt;defer tx.Rollback()&lt;/code&gt; 做兜底&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;结构体映射&lt;/td&gt;
&lt;td&gt;手写行→struct 拷贝&lt;/td&gt;
&lt;td&gt;sqlx &lt;code&gt;Get&lt;/code&gt;/&lt;code&gt;Select&lt;/code&gt; 自动映射&lt;/td&gt;
&lt;td&gt;tag &lt;code&gt;db:&amp;quot;col&amp;quot;&lt;/code&gt; 声明式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ORM&lt;/td&gt;
&lt;td&gt;手写/第三方（如 sqlpp11）&lt;/td&gt;
&lt;td&gt;GORM（AutoMigrate/关联）&lt;/td&gt;
&lt;td&gt;自动建表、crud、迁移&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;code&gt;err != nil&lt;/code&gt; 全链路&lt;/td&gt;
&lt;td&gt;每步都要查&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-databasesql-起步--open-与连接池"&gt;3.1 database/sql 起步 —— Open 与连接池&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sql.Open&lt;/code&gt; 并不会真的连数据库（&lt;code&gt;Ping&lt;/code&gt; 才触发真实连接），它返回的 &lt;code&gt;*sql.DB&lt;/code&gt; 是一个&lt;strong&gt;连接池句柄&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>数组与切片</title><link>https://www.sylgalaxy.xyz/posts/go-01-04/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-04/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 的序列容器：固定长度的数组与动态的切片——切片是 Go 中最常用的数据结构&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一c-对照速查表"&gt;一、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;std::array&amp;lt;T, N&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[N]T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 数组&lt;strong&gt;长度是类型的一部分&lt;/strong&gt;，&lt;code&gt;[3]int&lt;/code&gt; 和 &lt;code&gt;[4]int&lt;/code&gt; 是不同类型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;std::vector&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]T&lt;/code&gt;（切片）&lt;/td&gt;
&lt;td&gt;切片是底层数组的&lt;strong&gt;引用/视图&lt;/strong&gt;，不是独立容器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vector::push_back&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;append&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;append 返回新切片，&lt;strong&gt;必须重新赋值&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vector::size()&lt;/code&gt; / &lt;code&gt;capacity()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;len(s)&lt;/code&gt; / &lt;code&gt;cap(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;完全对应&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vector&amp;lt;T&amp;gt;&lt;/code&gt; 赋值&lt;/td&gt;
&lt;td&gt;切片赋值&lt;/td&gt;
&lt;td&gt;C++ vector 赋值是深拷贝；&lt;strong&gt;Go 切片赋值只是拷贝引用&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;std::vector&amp;lt;T&amp;gt;&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;==&lt;/code&gt; 比较&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[N]T&lt;/code&gt; 支持 &lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;切片&lt;strong&gt;不能&lt;/strong&gt;用 &lt;code&gt;==&lt;/code&gt; 比较（只能和 &lt;code&gt;nil&lt;/code&gt; 比）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心区别&lt;/strong&gt;：C++ 的 &lt;code&gt;std::vector&lt;/code&gt; 是一个拥有数据的容器；Go 的切片只是一个&amp;quot;窗口&amp;quot;——包含指针、长度、容量三个字段，指向某个底层数组。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二数组-nt"&gt;二、数组 [N]T&lt;/h2&gt;
&lt;h3 id="21-基本语法"&gt;2.1 基本语法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 声明：长度在类型中，不可省略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 零值：[0 0 0 0 0]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;go&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;world&amp;#34;&lt;/span&gt;} &lt;span style="color:#75715e"&gt;// 字面量初始化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#f92672"&gt;...&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;} &lt;span style="color:#75715e"&gt;// 编译器自动推断长度 = 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 长度是类型的一部分：[3]int 和 [4]int 是不同类型！&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// var x [3]int = [4]int{...} // 编译错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="22-数组是值类型与-c-stdarray-一致"&gt;2.2 数组是值类型（与 C++ std::array 一致）&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 值拷贝，b 是 a 的副本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;999&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 修改 b 不影响 a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [1 2 3]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [999 2 3]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="23-数组支持--比较"&gt;2.3 数组支持 == 比较&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// true——长度相同、元素逐个相等即可比较&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;实际使用&lt;/strong&gt;：Go 中几乎不用数组，绝大多数场景用切片。数组主要用于固定长度的场景（如 RGB 颜色 &lt;code&gt;[3]byte&lt;/code&gt;、矩阵维度等）。&lt;/p&gt;</description></item><item><title>逃逸分析与内存分配</title><link>https://www.sylgalaxy.xyz/posts/go-06-02/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-06-02/</guid><description>&lt;blockquote&gt;
&lt;p&gt;C++ 里 new/delete、智能指针、内存池全靠手写；Go 用逃逸分析 + 分级分配器把&amp;quot;栈还是堆&amp;quot;自动定好了&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;在 Go 里写 &lt;code&gt;x := 42&lt;/code&gt;，变量到底放栈上还是堆上，&lt;strong&gt;不由你说了算，由编译器说了算&lt;/strong&gt;。这个&amp;quot;说了算&amp;quot;的过程叫&lt;strong&gt;逃逸分析（escape analysis）&lt;/strong&gt;。它决定了一个变量能否安全地呆在栈上（函数返回就免费销毁），还是必须逃逸到堆（交给 GC 管理）。这直接关系到顺滑度、GC 压力与性能——理解了它，你就从&amp;quot;手动管内存&amp;quot;（C++）切换到&amp;quot;理解自动管内存&amp;quot;（Go）的思维。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：栈上分配 = 零 GC 压力、函数返回即释放；堆上分配 = 每次都要触发 GC 或分配器。逃逸分析的目标很简单：&lt;strong&gt;能放栈就不放堆&lt;/strong&gt;。用 &lt;code&gt;go build -gcflags=&amp;quot;-m&amp;quot;&lt;/code&gt; 就能窥见编译器的决策过程。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;int x;&lt;/code&gt;（RAII，作用域结束自动析构）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x := 42&lt;/code&gt;，若未逃逸&lt;/td&gt;
&lt;td&gt;Go 编译器决定，不是你决定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;堆上分配&lt;/td&gt;
&lt;td&gt;&lt;code&gt;new&lt;/code&gt; / &lt;code&gt;malloc&lt;/code&gt;，手动 &lt;code&gt;delete&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;变量逃逸时自动堆分配&lt;/td&gt;
&lt;td&gt;Go 无需/不能手动释放&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;智能指针&lt;/td&gt;
&lt;td&gt;&lt;code&gt;shared_ptr&lt;/code&gt; / &lt;code&gt;unique_ptr&lt;/code&gt; 管理引用&lt;/td&gt;
&lt;td&gt;GC 统一管理&lt;/td&gt;
&lt;td&gt;逃逸对象由 GC 回收，无引用计数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;返回局部对象&lt;/td&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;/td&gt;
&lt;td&gt;手写 &lt;code&gt;objpool&lt;/code&gt; / 复用 vector&lt;/td&gt;
&lt;td&gt;分配器内建（mcache → mcentral → mheap）&lt;/td&gt;
&lt;td&gt;Go 内置分级分配器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;大小类(size class)&lt;/td&gt;
&lt;td&gt;手写&lt;/td&gt;
&lt;td&gt;编译期确定，分配器按 size class 取块&lt;/td&gt;
&lt;td&gt;C++ 分配器可替代，Go 内建&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;td&gt;逃逸分析顺带优化拷贝去重&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;大对象堆分配&lt;/td&gt;
&lt;td&gt;依赖 malloc 行为&lt;/td&gt;
&lt;td&gt;&amp;gt;32KB 直接 mheap，不经过 mcache&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;code&gt;void*&lt;/code&gt; 转换，手动管理生命周期&lt;/td&gt;
&lt;td&gt;具体值→&lt;code&gt;interface{}&lt;/code&gt; 可能逃逸&lt;/td&gt;
&lt;td&gt;装箱常伴随逃逸&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-栈-vs-堆先建立直觉"&gt;3.1 栈 vs 堆：先建立直觉&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;┌─────────────────── 栈（Stack）───────────────────┐
│ main() 的帧 │
│ ├─ 局部变量 x: 42 ← 编译器决定放这 │
│ └─ 调用 f() 的帧 │
│ └─ f 返回时，这一帧整体弹出，&amp;#34;免费释放&amp;#34; │
└─────────────────────────────────────────────────┘
┌─────────────────── 堆（Heap）───────────────────┐
│ 对象：(指向它的指针被 main 拿走了) │
│ 生命周期：直到 GC 认为没人引用它才回收 │
│ 成本：分配（分配器查找空闲块）+ 回收（GC 扫描） │
└─────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;栈上的变量&lt;/strong&gt;：随函数帧创建/销毁。函数返回时，栈指针回落，整块内存&amp;quot;原地废弃&amp;quot;——&lt;strong&gt;无分配成本、无释放成本、无 GC 参与&lt;/strong&gt;。这正是 C++ 栈对象的免费午餐。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;堆上的变量&lt;/strong&gt;：生命周期逃出当前函数，必须由 GC 跟踪回收。分配要走分配器、回收要看 GC 何时跑，&lt;strong&gt;每一笔都有成本&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Go 与 C++ 的最大不同&lt;/strong&gt;：C++ 里 &lt;code&gt;int x;&lt;/code&gt; 一定在栈上、&lt;code&gt;new int&lt;/code&gt; 一定在堆上、返回局部变量地址=悬垂指针（未定义行为）。Go 里&lt;strong&gt;同一段代码，编译器可能让变量留在栈上，也可能挪去堆&lt;/strong&gt;——全看会不会&amp;quot;逃逸&amp;quot;出当前函数。返回局部变量的指针在 Go 里完全安全：&lt;/p&gt;</description></item><item><title>项目结构 internal/pkg/cmd</title><link>https://www.sylgalaxy.xyz/posts/go-04-03-internal-pkg-cmd/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-03-internal-pkg-cmd/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的目录与命名空间组织到 Go 的「包即边界」：cmd/internal/pkg 是社区事实标准&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 没有 C++ 头文件/源文件对，也没有 C++ 那种「目录 + 命名空间」两级组织。Go 的组织单位是&lt;strong&gt;包（package）&lt;/strong&gt;，一个目录一个包，&lt;code&gt;import&lt;/code&gt; 路径即模块路径 + 目录路径。一个可发布的 Go 项目结构，社区多年沉淀出了事实标准：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;repo&amp;gt;
├── cmd/ # 可执行程序入口（main 包）
├── internal/ # 私有代码：仅本项目可导入
├── pkg/ # 可复用库代码：对外公开
├── configs/ # 配置文件
├── scripts/ # 构建/运维脚本
└── go.mod
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;更向上看，Go 的哲学是 &lt;strong&gt;「包即层级」&lt;/strong&gt;：包之间靠 import 建立依赖，import 循环会被编译器直接拒绝——比 C++ 的循环 include 报错更早、更严格。这天然强制了「按层依赖」的架构。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;cmd&lt;/code&gt; / &lt;code&gt;internal&lt;/code&gt; / &lt;code&gt;pkg&lt;/code&gt; 不是语言强制，而是 golang-standards/project-layout 提出的&lt;strong&gt;事实约定&lt;/strong&gt;。真正由 Go 强制的是：&lt;code&gt;internal&lt;/code&gt; 的可见性规则、每个 &lt;code&gt;main&lt;/code&gt; 包是入口、包不能循环导入。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;命名空间（namespace）+ 头文件&lt;/td&gt;
&lt;td&gt;包（package）&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;code&gt;int main()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;package main&lt;/code&gt; + &lt;code&gt;func main()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;main 包即程序入口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;公共接口&lt;/td&gt;
&lt;td&gt;&lt;code&gt;namespace Foo&lt;/code&gt; 内公开符号&lt;/td&gt;
&lt;td&gt;大写导出 / 小写私有&lt;/td&gt;
&lt;td&gt;可见性跟&lt;strong&gt;标识符首字母&lt;/strong&gt;走&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;私有代码&lt;/td&gt;
&lt;td&gt;pimpl / 内部命名空间 / 隐藏符号&lt;/td&gt;
&lt;td&gt;&lt;code&gt;internal/&lt;/code&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;前置声明 + 复杂 include 图&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;编译器拒绝&lt;/strong&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;code&gt;.h&lt;/code&gt; 声明 + &lt;code&gt;.cpp&lt;/code&gt; 实现&lt;/td&gt;
&lt;td&gt;一个 &lt;code&gt;.go&lt;/code&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;module/backend/… 手工约定&lt;/td&gt;
&lt;td&gt;handler→service→repository&lt;/td&gt;
&lt;td&gt;由 import 依赖方向强制&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;td&gt;Go 鼓励多包、小接口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;测试辅助&lt;/td&gt;
&lt;td&gt;测试私有符号靠 friend/内部类&lt;/td&gt;
&lt;td&gt;&lt;code&gt;internal&lt;/code&gt; 包可见&lt;/td&gt;
&lt;td&gt;测试可直接放同包访问私有函数&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-标准布局总览cmd--internal--pkg"&gt;3.1 标准布局总览：cmd / internal / pkg&lt;/h3&gt;
&lt;p&gt;以 golang-standards/project-layout 为参考的常见布局：&lt;/p&gt;</description></item><item><title>原生 HTTP 服务 net/http</title><link>https://www.sylgalaxy.xyz/posts/go-05-02-http-net-http/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-05-02-http-net-http/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 Boost.Beast / Crow 到 Go：标准库就是一套完整的 HTTP 服务器，Handler 即函数签名&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;在 C++ 里写 HTTP 服务要选库（Boost.Beast 偏底层、Crow 要自己搭路由、Drogon 大而全），而在 Go 里&lt;strong&gt;标准库 &lt;code&gt;net/http&lt;/code&gt; 就是一个能上生产的基础 HTTP 服务框架&lt;/strong&gt;——路由、请求解析、响应写出、超时控制、优雅关闭全都有。它的核心哲学是「一个 &lt;code&gt;http.Handler&lt;/code&gt; 就是一个 http.ResponseWriter 参数 + 一个 *http.Request 参数的函数」，一切中间件、路由、框架都是这个接口的装饰与组合。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;Handler&lt;/code&gt; 是唯一的核心接口。Go 1.22 起 &lt;code&gt;http.ServeMux&lt;/code&gt; 原生支持「方法 + 路径」路由（&lt;code&gt;&amp;quot;GET /users/{id}&amp;quot;&lt;/code&gt;），标准库写 REST 服务不再需要任何第三方框架。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTP 库&lt;/td&gt;
&lt;td&gt;Boost.Beast / Crow / Drogon / cpp-httplib&lt;/td&gt;
&lt;td&gt;&lt;code&gt;net/http&lt;/code&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;继承 handler / 回调&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http.Handler&lt;/code&gt; 接口 + &lt;code&gt;http.HandlerFunc&lt;/code&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;Crow 手动匹配 / router 库&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http.NewServeMux&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 1.22+ 支持方法路由&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;路径参数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:id&lt;/code&gt; 需框架支持&lt;/td&gt;
&lt;td&gt;&lt;code&gt;r.PathValue(&amp;quot;id&amp;quot;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ServeMux 通配符 &lt;code&gt;{id}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;服务对象&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Crow::run()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http.Server&lt;/code&gt; 结构体&lt;/td&gt;
&lt;td&gt;超时/监听全是 Server 字段&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;会话/keep-alive&lt;/td&gt;
&lt;td&gt;手管 socket&lt;/td&gt;
&lt;td&gt;自动，&lt;code&gt;IdleTimeout&lt;/code&gt; 管空闲连接&lt;/td&gt;
&lt;td&gt;默认开启&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON 响应&lt;/td&gt;
&lt;td&gt;序列化库 + 手动 header&lt;/td&gt;
&lt;td&gt;&lt;code&gt;json.NewEncoder(w).Encode(v)&lt;/code&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;手写装饰器 / Crow 外挂&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func(http.Handler) http.Handler&lt;/code&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;code&gt;srv.Shutdown(ctx)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;标准库内置，等待在飞请求&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-最小-http-服务--handler-与-handlerfunc"&gt;3.1 最小 HTTP 服务 —— Handler 与 HandlerFunc&lt;/h3&gt;
&lt;p&gt;任何 HTTP 服务都绕不开这两个类型：&lt;/p&gt;</description></item><item><title>指针 (Pointers)</title><link>https://www.sylgalaxy.xyz/posts/go-01-08/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-08/</guid><description>&lt;p&gt;Go 保留了指针的核心能力（间接寻址、传地址），但砍掉了指针算术和引用类型 &lt;code&gt;&amp;amp;T&lt;/code&gt;，换来内存安全和 GC 兼容。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="c-对照速查表"&gt;C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;&lt;code&gt;int* p&lt;/code&gt; / &lt;code&gt;int *p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var p *int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 把 &lt;code&gt;*&lt;/code&gt; 放在&lt;strong&gt;类型前&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;取地址&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;x&lt;/code&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;code&gt;*p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*p&lt;/code&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;code&gt;p++&lt;/code&gt;, &lt;code&gt;p + n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;不支持&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Go 禁止，用切片代替&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;空指针&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NULL&lt;/code&gt; / &lt;code&gt;nullptr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nil&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 没有 NULL 关键字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;引用类型&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int&amp;amp; ref = x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;不存在&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Go 没有引用，统一用指针&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;new&lt;/td&gt;
&lt;td&gt;&lt;code&gt;new int&lt;/code&gt; (调用构造)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;new(int)&lt;/code&gt; → &lt;code&gt;*int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 的 new 只分配零值内存，不调用构造函数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;struct 访问&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ptr-&amp;gt;field&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ptr.field&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 编译器自动解引用，不需要 &lt;code&gt;-&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;make&lt;/td&gt;
&lt;td&gt;无对应物&lt;/td&gt;
&lt;td&gt;&lt;code&gt;make([]int, 5)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;仅用于 slice/map/channel，返回初始化后的值（不是指针）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="1-指针基础t"&gt;1. 指针基础：&amp;amp;、*、*T&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; = &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#75715e"&gt;// p 是指向 x 的指针，*int 表示&amp;#34;指向 int 的指针&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;x 的值：&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 解引用：通过指针读取值 → 42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;x 的地址：&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 打印地址 → 0xc0000b4008（类似）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; = &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 通过指针修改原变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;修改后 x：&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// → 100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 零值：指针的零值是 nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;q&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;q == nil:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;q&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// → true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;要点&lt;/strong&gt;：&lt;code&gt;*int&lt;/code&gt; 的 &lt;code&gt;*&lt;/code&gt; 是类型修饰符（&amp;ldquo;int 的指针&amp;rdquo;），&lt;code&gt;*p&lt;/code&gt; 的 &lt;code&gt;*&lt;/code&gt; 是操作符（&amp;ldquo;解引用&amp;rdquo;）。&lt;/p&gt;</description></item><item><title>字符串与 Rune</title><link>https://www.sylgalaxy.xyz/posts/go-01-10-rune/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-01-10-rune/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Go 字符串的本质、Unicode 处理与常用操作速查&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 的 &lt;code&gt;string&lt;/code&gt; 是&lt;strong&gt;不可变的字节序列&lt;/strong&gt;，底层以 UTF-8 编码存储。它是一个&lt;strong&gt;值类型&lt;/strong&gt;（赋值和传参都会拷贝），长度固定后不能修改。&lt;/p&gt;
&lt;p&gt;与 C++ &lt;code&gt;std::string&lt;/code&gt; 最大的区别：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;不可变&lt;/strong&gt;——没有 &lt;code&gt;operator[]&lt;/code&gt; 返回引用，不能就地修改字符&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UTF-8 原生支持&lt;/strong&gt;——但 &lt;code&gt;len()&lt;/code&gt; 返回的是&lt;strong&gt;字节数&lt;/strong&gt;，不是字符数&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;rune&lt;/code&gt; 类型&lt;/strong&gt;——用于表示单个 Unicode 码点（&lt;code&gt;int32&lt;/code&gt; 别名）&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;C++&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;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 是不可变值类型；C++ 可变&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rune&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;char32_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rune&lt;/code&gt; = &lt;code&gt;int32&lt;/code&gt;，表示一个 Unicode 码点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;byte&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uint8&lt;/code&gt; / &lt;code&gt;unsigned char&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一个字节&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;len(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;s.size()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 返回&lt;strong&gt;字节数&lt;/strong&gt;，不是字符数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s[i]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;s[i]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 返回 &lt;code&gt;byte&lt;/code&gt;；C++ 返回 &lt;code&gt;char&amp;amp;&lt;/code&gt;（可写）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for _, r := range s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for (char32_t c : s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 遍历 rune；C++ 依赖编码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strings.Builder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::ostringstream&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;高效字符串拼接&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strconv.Itoa(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::to_string(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;整数转字符串&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strconv.Atoi(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::stoi(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字符串转整数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strings.Contains&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;std::string::find&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;判断子串是否存在&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[]byte(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;reinterpret_cast&lt;/code&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;code&gt;std::string&lt;/code&gt; 构造&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt; 和 &lt;code&gt;[]byte&lt;/code&gt; 必须显式转换&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三代码示例"&gt;三、代码示例&lt;/h2&gt;
&lt;h3 id="31-string-底层不可变字节序列"&gt;3.1 string 底层：不可变字节序列&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Hello, 世界&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;len:&amp;#34;&lt;/span&gt;, len(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 13（字节数！不是字符数）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// s[0] = &amp;#39;h&amp;#39; // 编译错误！字符串不可变&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 底层就是字节数组的只读视图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []byte(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 转为 []byte 后可修改&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] = &lt;span style="color:#e6db74"&gt;&amp;#39;h&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s2&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; string(&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 再转回 string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s2&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// hello, 世界&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-rune-类型与-byte-vs-rune"&gt;3.2 rune 类型与 byte vs rune&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Go语言&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// byte —— 字节视角&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;字节数:&amp;#34;&lt;/span&gt;, len(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 8（G=1, o=1, 语=3, 言=3）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// rune —— 字符视角&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;runes&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []rune(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;字符数:&amp;#34;&lt;/span&gt;, len(&lt;span style="color:#a6e22e"&gt;runes&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 每个 rune 是一个 int32，代表一个 Unicode 码点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;语 的 Unicode: U+%04X\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;runes&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]) &lt;span style="color:#75715e"&gt;// U+8BED&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="33-遍历字符串range-vs-索引"&gt;3.3 遍历字符串：range vs 索引&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Hello世界&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式一：for range —— 按 rune 遍历（推荐用于字符级操作）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;=== for range ===&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;字节索引 %d, rune: %c (U+%04X)\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 输出：H(0), e(1), l(2), l(3), o(4), 世(5), 界(8)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 注意：i 是字节索引！&amp;#34;世&amp;#34;从第5字节开始，占3字节，&amp;#34;界&amp;#34;从第8字节开始&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式二：for i —— 按字节遍历&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;=== for i (字节) ===&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &amp;lt; len(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;s[%d] = 0x%02X\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 中文字符的字节是 0xE4 0xB8 0xAD 这样的三字节序列&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 方式三：转为 []rune 后按索引遍历&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []rune(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &amp;lt; len(&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;r[%d] = %c\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="34-utf8-包"&gt;3.4 utf8 包&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;unicode/utf8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Go语言&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 获取 rune 数量（等价于 len([]rune(s)) 但更高效）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;字符数:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;utf8&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;RuneCountInString&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 验证是否为合法 UTF-8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;合法 UTF-8:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;utf8&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ValidString&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 非法 UTF-8 字节&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;bad&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;{&lt;span style="color:#ae81ff"&gt;0xCE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBA&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xE1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBD&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB9&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCF&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0x83&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xBC&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xCE&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0xB5&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;合法:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;utf8&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Valid&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;bad&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// RuneLen 返回某个 rune 编码后占多少字节&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;语 占字节:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;utf8&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;RuneLen&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;语&amp;#39;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="35-strings-包常用函数"&gt;3.5 strings 包常用函数&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34; Hello, Go World! &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 查找&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;HasPrefix&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; Hello&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;HasSuffix&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;! &amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Contains&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Index&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 10（字节索引）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 裁剪&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TrimSpace&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;Hello, Go World!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Trim&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; !&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;Hello, Go World&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TrimLeft&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; H&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;ello, Go World! &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TrimSuffix&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;test.go&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;.go&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;test&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TrimPrefix&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;cmd/test.go&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;cmd/&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;test.go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 替换&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Replace&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;aabbcc&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;bb&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;xx&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;aaxxcc&amp;#34; (只替换1次)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReplaceAll&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;aabbcc&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;xxbbcc&amp;#34; (替换所有)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReplaceAll&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;aabbcc&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;bb&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;aacc&amp;#34; (删除子串)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 分割与合并&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;parts&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Split&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;a,b,c&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [&amp;#34;a&amp;#34;, &amp;#34;b&amp;#34;, &amp;#34;c&amp;#34;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;joined&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Join&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;parts&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;a-b-c&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;joined&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 大小写&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ToUpper&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;HELLO&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ToLower&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;HELLO&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Title&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;hello go&amp;#34;&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;Hello Go&amp;#34; (1.18 后建议用 cases)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 重复与填充&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Repeat&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ab&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;ababab&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Repeat&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;====================&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 字段分割（按空白字符）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fields&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fields&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34; foo bar baz &amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fields&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [foo bar baz]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="36-strconv-包类型转换"&gt;3.6 strconv 包：类型转换&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;strconv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 整数 ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// int -&amp;gt; string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Itoa&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FormatInt&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;11111111&amp;#34; (二进制)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// string -&amp;gt; int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Atoi&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;42&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;转换失败:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;n&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 更灵活的解析&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;n2&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ParseInt&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;FF&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 十六进制 -&amp;gt; int64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;n2&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 255&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 布尔 ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ParseBool&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FormatBool&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 浮点数 ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ParseFloat&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;3.14159&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 3.14159&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 浮点数格式化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FormatFloat&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3.14159&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;f&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;3.14&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FormatFloat&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0.15&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;f&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;0.1500000000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;strconv&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;FormatFloat&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3.14159&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;e&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;3.1416e+00&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="37-string-与-byte-的转换"&gt;3.7 string 与 []byte 的转换&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;你好世界&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// string -&amp;gt; []byte（拷贝！底层数组不共享）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []byte(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] = &lt;span style="color:#e6db74"&gt;&amp;#39;x&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 修改不影响原字符串&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(string(&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;x好世界&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;你好世界&amp;#34;（原字符串不变）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// string -&amp;gt; []rune（按字符拆分）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []rune(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] = &lt;span style="color:#e6db74"&gt;&amp;#39;我&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(string(&lt;span style="color:#a6e22e"&gt;r&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// &amp;#34;我好世界&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 频繁转换的性能提示：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 如果需要反复读取 []byte，先转换一次再复用，不要反复转&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="38-字符串拼接三种方式"&gt;3.8 字符串拼接：三种方式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 方式一：+ 运算符（简单场景，少量拼接） ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;hello&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;, &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;World!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;hello&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 注意：每次 + 都会分配新内存并拷贝&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 循环中使用 + 拼接性能差（O(n^2)）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 方式二：strings.Builder（推荐，高效） ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Grow&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 预分配容量（可选但推荐）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt; &amp;lt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WriteString&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;item%d &amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;item0 item1 item2 ... item9 &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 也可以用 WriteByte, WriteRune&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Reset&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WriteString&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Go&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WriteByte&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;!&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// &amp;#34;Go!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 方式三：strings.Join（拼接已有切片） ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;items&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;apple&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;banana&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;cherry&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;joined&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Join&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;items&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; | &amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;joined&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;apple | banana | cherry&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="39-fmtsprintf-格式化"&gt;3.9 fmt.Sprintf 格式化&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 基本格式化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;整数: %d, 浮点: %f, 字符串: %s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3.14&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Sprintf 返回字符串而非打印&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;年龄: %d, 成绩: %.1f%%&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;95.5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#34;年龄: 18, 成绩: 95.5%&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 常用格式动词&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;十进制: %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;八进制: %o\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 377&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;十六进制: %x\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// ff&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;十六进制(大写): %X\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// FF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;二进制: %b\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 11111111&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Unicode: %U\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;语&amp;#39;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// U+8BED&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;字符: %c\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8364&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// € (欧元符号)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 宽度与对齐&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;[%10s]\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [ right]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;[%-10s]\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [left ]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;[%05d]\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [00042]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 结构体格式化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Age&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%+v\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// {Name:Alice Age:30}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%#v\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// main.Person{Name:&amp;#34;Alice&amp;#34;, Age:30}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%T\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// main.Person&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 错误处理常用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;文件 %s 不存在 (行号: %d)&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;config.txt&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="310-多行字符串"&gt;3.10 多行字符串&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 反引号：原生字符串（推荐） ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 不能包含反引号本身，不处理转义符&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;raw&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 第一行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 第二行（有缩进）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; \n 这不是换行，是字面量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; `&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;raw&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ---- 双引号 + 转义 ----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;escaped&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;第一行\n第二行\n\t\t缩进\n路径: C:\\Users\\test&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;escaped&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 反引号常用于：正则、SQL、模板、路径&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;regex&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`^\d{3}-\d{4}$`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;regex&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 不需要转义反斜杠&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="四常见坑"&gt;四、常见坑&lt;/h2&gt;
&lt;h3 id="坑-1len-返回字节数不是字符数"&gt;坑 1：len() 返回字节数，不是字符数&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;你好&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(len(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 6，不是 2！&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;utf8&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;RuneCountInString&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;// 2（正确获取字符数）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;教训&lt;/strong&gt;：涉及中文等多字节字符时，用 &lt;code&gt;utf8.RuneCountInString()&lt;/code&gt; 或 &lt;code&gt;len([]rune(s))&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>综合项目实战记录（短链接服务）</title><link>https://www.sylgalaxy.xyz/posts/go-05-05/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-05-05/</guid><description>&lt;blockquote&gt;
&lt;p&gt;把前面四篇的东西缝合起来：一个「从需求到 Docker 部署」的完整短链接服务，走一遍 Go 工程化的真实流程&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;短链接服务是一个完美的「毕业设计」：需求明确、覆盖路由/存储/并发/测试/构建全链路、不引入任何第三方 Web 框架也能跑（正适合巩固 net/http）。本文按真实开发顺序走：&lt;strong&gt;需求分析 → 目录设计 → 存储接口 → 短码生成 → HTTP 路由 → 计数 → 单元测试 → go mod → 构建与 Docker&lt;/strong&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：这个项目刻意只用标准库写 HTTP（把 &lt;a href="02-%E5%8E%9F%E7%94%9FHTTP%E6%9C%8D%E5%8A%A1-net-http.md"&gt;02-原生HTTP服务-net-http&lt;/a&gt; 练扎实），存储接口先给内存实现、日后可平移到 &lt;a href="04-%E6%95%B0%E6%8D%AE%E5%BA%93%E6%8E%A5%E5%85%A5-database-sql-gorm-sqlx.md"&gt;04-数据库接入-database-sql-gorm-sqlx&lt;/a&gt; 的 database/sql/gorm。它演示的是 Go 工程化的&lt;strong&gt;结构&lt;/strong&gt;：&lt;code&gt;cmd/&lt;/code&gt; 装入口、&lt;code&gt;internal/&lt;/code&gt; 装业务、&lt;code&gt;store&lt;/code&gt; 是抽象边界。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&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;/td&gt;
&lt;td&gt;src/ + CMake targets&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cmd/&lt;/code&gt; + &lt;code&gt;internal/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;目录即包，internal 强制隔离&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;code&gt;interface{}&lt;/code&gt; 接口（store.URLStore）&lt;/td&gt;
&lt;td&gt;鸭子类型式，一个接口多个实现&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;短码生成&lt;/td&gt;
&lt;td&gt;自写 base62&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;code&gt;Location&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http.Redirect(w, r, url, 302)&lt;/code&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;code&gt;std::mutex&lt;/code&gt; / &lt;code&gt;std::atomic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sync.RWMutex&lt;/code&gt; + map&lt;/td&gt;
&lt;td&gt;读写锁分离，并发读不死锁&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单元测试&lt;/td&gt;
&lt;td&gt;gtest/test framework&lt;/td&gt;
&lt;td&gt;&lt;code&gt;testing&lt;/code&gt; + &lt;code&gt;go test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;table-driven 是惯例&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;构建&lt;/td&gt;
&lt;td&gt;CMake/ninja&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go build ./cmd/server&lt;/code&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;手写 Dockerfile 依赖编译环境&lt;/td&gt;
&lt;td&gt;&lt;code&gt;golang&lt;/code&gt; builder 镜像 + 多阶段&lt;/td&gt;
&lt;td&gt;官方镜像成熟，CGO 关掉即纯静态&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;p&gt;本项目按「需求 → 结构 → 代码 → 测试 → 构建 → 部署」的顺序推进，每一小步都有可直接运行的代码片段。&lt;/p&gt;</description></item><item><title>STM32 GPIO 入门三连：点亮 LED、流水灯与蜂鸣器</title><link>https://www.sylgalaxy.xyz/posts/stm32-gpio-led-buzzer/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/stm32-gpio-led-buzzer/</guid><description>&lt;p&gt;环境配好、接线踩坑之后，接下来就是让外设动起来。这组实验全部围绕 GPIO 输出：先点亮一颗 LED，再扩展成八路流水灯，最后用同样的思路驱动蜂鸣器。三个实验的代码都在工程的 &lt;code&gt;User\main.c&lt;/code&gt; 里（如 &lt;code&gt;3-1点亮LED灯&lt;/code&gt;、&lt;code&gt;3-2流水灯&lt;/code&gt;、&lt;code&gt;3-3蜂鸣器&lt;/code&gt;）。&lt;/p&gt;
&lt;h2 id="一点亮第一颗-led"&gt;一、点亮第一颗 LED&lt;/h2&gt;
&lt;p&gt;之前两天都在跟接线较劲，怀疑人生；当 LED 终于亮起来的时候，成就感爆棚。&lt;strong&gt;核心教训：嵌入式开发，硬件接线和软件一样重要。&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// PA0 配置为推挽输出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GPIO_InitStructure.GPIO_Pin &lt;span style="color:#f92672"&gt;=&lt;/span&gt; GPIO_Pin_0;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GPIO_InitStructure.GPIO_Mode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; GPIO_Mode_Out_PP; &lt;span style="color:#75715e"&gt;// 推挽输出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GPIO_InitStructure.GPIO_Speed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; GPIO_Speed_50MHz;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;GPIO_Init&lt;/span&gt;(GPIOA, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;GPIO_InitStructure);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 低电平点亮 LED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;GPIO_ResetBits&lt;/span&gt;(GPIOA, GPIO_Pin_0);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键理解：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GPIO 配置：推挽输出模式，速度 50MHz&lt;/li&gt;
&lt;li&gt;LED 驱动：低电平有效，&lt;code&gt;GPIO_ResetBits&lt;/code&gt; 拉低点亮&lt;/li&gt;
&lt;li&gt;当前状态：常亮，&lt;code&gt;while(1)&lt;/code&gt; 为空&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二流水灯pa0-pa7-八个-led"&gt;二、流水灯：PA0-PA7 八个 LED&lt;/h2&gt;
&lt;p&gt;在单颗 LED 的基础上，实现 PA0-PA7 八个 LED 流水灯效果。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 配置 GPIOA 所有引脚为推挽输出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GPIO_InitStructure.GPIO_Pin &lt;span style="color:#f92672"&gt;=&lt;/span&gt; GPIO_Pin_All; &lt;span style="color:#75715e"&gt;// 一次性配置所有引脚
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;GPIO_Init&lt;/span&gt;(GPIOA, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;GPIO_InitStructure);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 流水灯核心：GPIO_Write 一次写入 16 位数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;GPIO_Write&lt;/span&gt;(GPIOA, &lt;span style="color:#f92672"&gt;~&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0x0001&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 0x0001取反=0xFFFE，PA0低电平点亮
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Delay_ms&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;GPIO_Write&lt;/span&gt;(GPIOA, &lt;span style="color:#f92672"&gt;~&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0x0002&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// PA1点亮
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Delay_ms&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;GPIO_Write&lt;/span&gt;(GPIOA, &lt;span style="color:#f92672"&gt;~&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0x0004&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// PA2点亮
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ... 依次类推到 PA7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="gpio-操作函数对比"&gt;GPIO 操作函数对比&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;函数&lt;/th&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;GPIO_ResetBits&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;单引脚拉低&lt;/td&gt;
&lt;td&gt;单个LED控制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GPIO_SetBits&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;单引脚拉高&lt;/td&gt;
&lt;td&gt;单个LED控制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GPIO_WriteBit&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;GPIO_Write&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16位整体写入&lt;/td&gt;
&lt;td&gt;多引脚同时控制&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="位操作技巧"&gt;位操作技巧&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~0x0001&lt;/code&gt; = &lt;code&gt;0xFFFE&lt;/code&gt; → PA0 低电平（点亮），其余高电平（熄灭）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~0x0002&lt;/code&gt; = &lt;code&gt;0xFFFD&lt;/code&gt; → PA1 低电平（点亮）&lt;/li&gt;
&lt;li&gt;位左移：&lt;code&gt;0x0001 &amp;lt;&amp;lt; n&lt;/code&gt; 可以简化代码&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="优化思路"&gt;优化思路&lt;/h3&gt;
&lt;p&gt;当前代码是 8 行重复，可以用循环 + 移位简化：&lt;/p&gt;</description></item><item><title>STM32 学习 Day01：开发环境配置与面包板接线踩坑</title><link>https://www.sylgalaxy.xyz/posts/stm32-day01-env-setup/</link><pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/stm32-day01-env-setup/</guid><description>&lt;p&gt;STM32 学习第一天：配置开发环境、熟悉 ST-Link 调试器、学面包板接线。技术内容不多，但接线的两个坑值得记下来。&lt;/p&gt;
&lt;h2 id="一完成内容"&gt;一、完成内容&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;配置 STM32 开发环境&lt;/li&gt;
&lt;li&gt;熟悉 ST-Link 调试器使用&lt;/li&gt;
&lt;li&gt;学习面包板接线基础&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二挫折与踩坑"&gt;二、挫折与踩坑&lt;/h2&gt;
&lt;h3 id="挫折-1供电原理不懂"&gt;挫折 1：供电原理不懂&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;不知道最小系统板如何为面包板供电&lt;/li&gt;
&lt;li&gt;浪费大量时间在接线上，LED 一直不亮&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教训&lt;/strong&gt;：先搞清楚供电回路，再动手接线&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="挫折-2接线思维误区"&gt;挫折 2：接线思维误区&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;误认为面包板格子位置是唯一的对应关系&lt;/li&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;/ul&gt;
&lt;h2 id="三收获"&gt;三、收获&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ST-Link 调试器接线已熟练掌握&lt;/li&gt;
&lt;li&gt;开发板接线基本熟悉&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第一天的核心体会：接线问题比想象中更消耗时间——供电回路和引脚对应关系没搞清楚之前，LED 不亮根本无从判断是哪里的问题。&lt;/p&gt;</description></item><item><title>C++ 服务部署实战：从源码到公网访问</title><link>https://www.sylgalaxy.xyz/posts/cpp-http-server-deploy/</link><pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-http-server-deploy/</guid><description>&lt;blockquote&gt;
&lt;p&gt;在一台 2C2G 的云服务器上实测：单文件 HTTP 服务器，&lt;code&gt;g++&lt;/code&gt; 编译，监听 8080 端口，从编译到公网访问全流程跑通。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="1-socket-七步流程"&gt;1. socket 七步流程&lt;/h2&gt;
&lt;p&gt;示例是一个约 60 行的单文件程序 &lt;code&gt;http_server.cpp&lt;/code&gt;，纯 Linux socket API、零第三方依赖，放在你自己的项目目录里即可。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;socket() → bind() → listen() → accept() → recv() → send() → close()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 建电话 插网线 开机待命 接电话 听需求 答复 挂断
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;步骤&lt;/th&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;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;socket(AF_INET, SOCK_STREAM, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;IPv4 + TCP，返回文件描述符（Linux 一切皆文件）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bind(fd, &amp;amp;addr, sizeof)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;绑定地址；&lt;code&gt;INADDR_ANY&lt;/code&gt;（0.0.0.0）= 监听所有网卡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;listen(fd, 16)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;开始待命；16 是 backlog 等待队列长度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;accept(fd, ...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;阻塞等客户端，返回新 fd（每客户一个）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;recv(fd, buf, n, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读 HTTP 请求报文（原始文本）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;send(fd, resp, len, 0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;回 HTTP 响应&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;close(fd)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;挂断，回 while 等下一客&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;要点：&lt;/p&gt;</description></item><item><title>C++ 后端学习路线：以云服务器为练兵场</title><link>https://www.sylgalaxy.xyz/posts/cpp-backend-roadmap/</link><pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cpp-backend-roadmap/</guid><description>&lt;blockquote&gt;
&lt;p&gt;目标：从零起步，拿一台 2C2G 的云服务器当主战场，系统学习 C++ 后端开发。
原则：基础 → 系统 → 网络 → 框架 → 工程化，渐进推进；&lt;strong&gt;每个阶段都在云服务器上产出可运行的作品&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="总览"&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;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;0&lt;/td&gt;
&lt;td&gt;Linux 基础与服务器上手&lt;/td&gt;
&lt;td&gt;起步阶段，边用边补&lt;/td&gt;
&lt;td&gt;workspace 工作目录、用户与权限体系&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;现代 C++ 核心&lt;/td&gt;
&lt;td&gt;2-4 周&lt;/td&gt;
&lt;td&gt;编译与工具链的熟练度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Linux 系统与网络编程&lt;/td&gt;
&lt;td&gt;4-6 周&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;手写并发 HTTP 服务器&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;框架与中间件&lt;/td&gt;
&lt;td&gt;6-8 周&lt;/td&gt;
&lt;td&gt;Drogon + MySQL + Redis 的 REST API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;工程化与云原生&lt;/td&gt;
&lt;td&gt;持续&lt;/td&gt;
&lt;td&gt;Docker 化部署 + CI/CD + 监控&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;时长按「每天 1-2 小时」估算，弹性理解；项目驱动，不以周数为硬指标。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;阶段 0 不必一次啃完：进程管理、看日志、shell 脚本这些内容在后面每个阶段都会反复用到，随用随补即可。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="阶段-0linux-基础与服务器上手"&gt;阶段 0：Linux 基础与服务器上手&lt;/h2&gt;
&lt;p&gt;这一层要覆盖的内容：&lt;/p&gt;</description></item><item><title>Linux 基础操作：目录结构、磁盘分区与权限</title><link>https://www.sylgalaxy.xyz/posts/linux-directory-disk-permission/</link><pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/linux-directory-disk-permission/</guid><description>&lt;blockquote&gt;
&lt;p&gt;适用读者：有 C++/Qt 基础（熟悉 &lt;code&gt;QDir&lt;/code&gt; / &lt;code&gt;QFile&lt;/code&gt;），手边有一台云服务器（示例环境：Alibaba Cloud Linux，2 核 / 2G / 40G 系统盘）。
主线：每条命令都在真实服务器上跑过，边用边理解。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="1-根目录里都有什么"&gt;1. 根目录里都有什么&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ls /&lt;/code&gt; 看到的目录（Alibaba Cloud Linux 实测）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bin dev home lib64 media opt root sbin swapfile tmp var
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;boot etc lib lost+found mnt proc run srv sys usr
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些目录&lt;strong&gt;不是平级无关的文件夹&lt;/strong&gt;，而是各司其职（FHS 标准约定）：&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;th&gt;类比 Windows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/etc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;系统与服务配置文件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Windows\System32&lt;/code&gt; 配置&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/usr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;系统软件与库（最大）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Program Files&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/var&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;经常变化的数据：日志、缓存&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\ProgramData&lt;/code&gt; 日志&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/home&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;普通用户的家目录&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Users\&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/root&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;root 用户的家目录&lt;/strong&gt;（不在 &lt;code&gt;/home&lt;/code&gt; 里）&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/tmp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;临时文件，重启可能清空&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%TEMP%&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/opt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;第三方大软件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;D:\Software&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/boot&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;/proc&lt;/code&gt; &lt;code&gt;/sys&lt;/code&gt; &lt;code&gt;/dev&lt;/code&gt; &lt;code&gt;/run&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;内存虚拟文件系统&lt;/strong&gt;，不在磁盘上&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lost+found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ext4 文件系统 fsck 修复碎片（有它说明 &lt;code&gt;/&lt;/code&gt; 是 ext4）&lt;/td&gt;
&lt;td&gt;磁盘扫描碎片&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;swapfile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;交换文件（小内存机器用文件代替交换分区）&lt;/td&gt;
&lt;td&gt;虚拟内存 &lt;code&gt;pagefile.sys&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;code&gt;/proc&lt;/code&gt; 里的数字目录就是进程 PID——内核把进程信息伪装成文件给你看，&lt;code&gt;cat /proc/cpuinfo&lt;/code&gt; 就是读 CPU 信息。&lt;/p&gt;</description></item><item><title>最常用 Git 命令速查：三区模型、场景命令表与五个坑</title><link>https://www.sylgalaxy.xyz/posts/git-essential-commands/</link><pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/git-essential-commands/</guid><description>&lt;blockquote&gt;
&lt;p&gt;适用人群：Git 零基础起步，以日常笔记仓库为练习场。
主线：先记住「三区模型」，命令自然就懂了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="1-核心要点先建立三区心智模型"&gt;1. 核心要点：先建立「三区」心智模型&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：90% 的 Git 疑惑都源于不知道「文件现在在哪个区」。Git 有三个区域——&lt;strong&gt;工作区 → 暂存区 → 本地仓库&lt;/strong&gt;，再加一个&lt;strong&gt;远程仓库&lt;/strong&gt;。所有常用命令本质上就是在这些区之间搬东西。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;工作区 暂存区 本地仓库 远程仓库
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(你编辑的文件) (git add 后) (git commit 后) (GitHub 等)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ git add │ git commit │ git push │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├──────────────▶├─────────────────▶ ├───────────────────▶ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │◀──────────────┤◀───────────────── ├── ◀─────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; │ git restore │ │ git fetch / pull │
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;区&lt;/th&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;/td&gt;
&lt;td&gt;你正在编辑的目录&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git status&lt;/code&gt; 里红色的文件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;暂存区&lt;/td&gt;
&lt;td&gt;下次 commit 要打包的内容&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git add&lt;/code&gt; 之后变绿色的文件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;本地仓库&lt;/td&gt;
&lt;td&gt;已提交的历史（&lt;code&gt;.git/&lt;/code&gt; 目录）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git log&lt;/code&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;code&gt;git push&lt;/code&gt; / &lt;code&gt;git pull&lt;/code&gt; 打交道&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="2-常用命令速查表按场景"&gt;2. 常用命令速查表（按场景）&lt;/h2&gt;
&lt;h3 id="21-首次配置与建仓"&gt;2.1 首次配置与建仓&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;命令&lt;/th&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;git config --global user.name &amp;quot;xxx&amp;quot;&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;git config --global user.email &amp;quot;xxx@xx.com&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;设置全局邮箱&lt;/td&gt;
&lt;td&gt;GitHub 用它关联头像/贡献图&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;当前目录变成 Git 仓库&lt;/td&gt;
&lt;td&gt;生成隐藏的 &lt;code&gt;.git/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git clone &amp;lt;url&amp;gt;&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;h3 id="22-日常四件套用得最多"&gt;2.2 日常四件套（用得最多）&lt;/h3&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;git status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;看当前状态：哪些改了、哪些暂存了（&lt;strong&gt;最常打&lt;/strong&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git add &amp;lt;file&amp;gt;&lt;/code&gt; / &lt;code&gt;git add .&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;把文件放入暂存区；&lt;code&gt;.&lt;/code&gt; 表示全部&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git commit -m &amp;quot;说明&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;把暂存区内容打包成一次提交&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git log --oneline&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一行一条看提交历史&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="23-查看差异与历史"&gt;2.3 查看差异与历史&lt;/h3&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;git diff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;工作区 vs 暂存区的改动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git diff --staged&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;暂存区 vs 上次提交的改动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git show &amp;lt;commit&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;看某次提交的具体内容&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git blame &amp;lt;file&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;看文件每行是谁、哪次提交写的&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="24-撤销与回退救火"&gt;2.4 撤销与回退（救火）&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;命令&lt;/th&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;git restore &amp;lt;file&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;丢弃工作区改动（未 add）&lt;/td&gt;
&lt;td&gt;⚠️ 改动不可恢复&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git restore --staged &amp;lt;file&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;取消暂存（add 反悔），保留改动&lt;/td&gt;
&lt;td&gt;安全&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git reset --soft HEAD~1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;撤销上次 commit，&lt;strong&gt;保留&lt;/strong&gt;改动在暂存区&lt;/td&gt;
&lt;td&gt;安全，改说明重提最常用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git revert &amp;lt;commit&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;生成一个「反向提交」抵消指定提交&lt;/td&gt;
&lt;td&gt;✅ 最安全，适合已 push 的场景&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="25-分支"&gt;2.5 分支&lt;/h3&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;git branch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;列出本地分支，&lt;code&gt;*&lt;/code&gt; 标记当前分支&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git branch &amp;lt;名字&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;新建分支（不切换）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git switch &amp;lt;名字&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;切换分支&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git switch -c &amp;lt;名字&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;新建并切换（= &lt;code&gt;-b&lt;/code&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git merge &amp;lt;分支&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;把指定分支合并进当前分支&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git branch -d &amp;lt;名字&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;删除已合并的分支&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="26-远程协作"&gt;2.6 远程协作&lt;/h3&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;git remote -v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;看远程仓库名和地址&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git remote add origin &amp;lt;url&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;关联一个远程仓库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git push -u origin main&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;首次推送并建立跟踪关系&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;推送（之后简写即可）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git fetch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只下载远程更新，不合并（先看看再说）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git pull&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;下载并合并 = &lt;code&gt;fetch&lt;/code&gt; + &lt;code&gt;merge&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="3-高频组合拳"&gt;3. 高频组合拳&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 场景1:日常保存进度(写笔记的标准流程)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git status &lt;span style="color:#75715e"&gt;# 先看有什么变动&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git add path/to/note.md &lt;span style="color:#75715e"&gt;# 只加想提交的文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git commit -m &lt;span style="color:#e6db74"&gt;&amp;#34;feat(模块): 添加 xx 笔记&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 场景2:commit 说明写错了,想重写&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git reset --soft HEAD~1 &lt;span style="color:#75715e"&gt;# 退回但保留改动&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git commit -m &lt;span style="color:#e6db74"&gt;&amp;#34;正确的说明&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 场景3:某个文件改坏了,恢复到最后一次提交的状态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git restore 文件名
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 场景4:push 被拒(远程有新提交)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git pull &lt;span style="color:#75715e"&gt;# 先拉下来合并&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push &lt;span style="color:#75715e"&gt;# 再推&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 场景5:实验性改动,开个分支玩&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git switch -c try-something
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ...随便折腾...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git switch main &lt;span style="color:#75715e"&gt;# main 完全不受影响&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="4-常见坑与误区"&gt;4. 常见坑与误区&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;⚠️ &lt;strong&gt;坑 1：把不该提交的文件 add 进去了&lt;/strong&gt;（如编辑器/助手的本地配置、进度笔记等本地配置层）
→ 现象：&lt;code&gt;git status&lt;/code&gt; 里出现不想推的文件。
→ 原因：&lt;code&gt;git add .&lt;/code&gt; 会把所有文件一网打尽。
→ 正确写法：精确指定文件名来 add；长期排除则写进 &lt;code&gt;.gitignore&lt;/code&gt;；已被跟踪的用 &lt;code&gt;git rm --cached 文件名&lt;/code&gt; 取消跟踪（本地文件保留）。&lt;/p&gt;</description></item><item><title>云服务器认识与使用：从虚拟机到公网部署</title><link>https://www.sylgalaxy.xyz/posts/cloud-server-intro/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/cloud-server-intro/</guid><description>&lt;blockquote&gt;
&lt;p&gt;适用读者：有 C++/Qt 开发基础，用 VMware 虚拟机跑过 Linux、做过 Qt 界面开发，正在学 Go，手边有一台入门配置的云服务器（示例：2 核 / 2G / 40G）。
主线：先用起来，再理解原理。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="1-认识你买的到底是台什么机器"&gt;1. 认识：你买的到底是台什么机器&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：云服务器不是神秘的新东西——它就是「一台放在数据中心里、常年开机、你通过 SSH 远程使用的 Linux 电脑」，和你在 VMware 里装的那台 Ubuntu 骨子里是同一种东西。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="11-先回忆你在虚拟机里做过什么"&gt;1.1 先回忆：你在虚拟机里做过什么&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;用 VMware 装一个 Ubuntu 服务器版，在里面跑现成的后端程序、做 Qt 界面开发。&lt;/li&gt;
&lt;li&gt;这台 Ubuntu 是「一台软件模拟出来的电脑」，运行在你自己的 Windows 上。&lt;/li&gt;
&lt;li&gt;你能 &lt;code&gt;ssh&lt;/code&gt; 连它、在里面装服务、跑程序——这些和云服务器上的操作&lt;strong&gt;几乎一模一样&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 为什么先从虚拟机讲起：你已经在「一台假的服务器」上做过大部分操作了。云服务器只是把「这台假的」换成「一台真的、别人帮你放在机房的」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="12-两个易混的词服务器和服务端"&gt;1.2 两个易混的词：「服务器」和「服务端」&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;词&lt;/th&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;strong&gt;服务器 (Server)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;一台&lt;strong&gt;长期开机的电脑&lt;/strong&gt;（硬件 + 系统）&lt;/td&gt;
&lt;td&gt;你的云上主机、机房里的物理机&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;服务端 (Server-side)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;一种&lt;strong&gt;软件的运行角色&lt;/strong&gt;，相对客户端而言&lt;/td&gt;
&lt;td&gt;你用 Qt 写的 TCP Server、Nginx、MySQL、Go 的 HTTP 服务&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;——这一点正是第 2 章的核心。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="13-一台服务器由什么组成"&gt;1.3 一台服务器由什么组成&lt;/h3&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;/td&gt;
&lt;td&gt;CPU、内存、磁盘、网卡——决定这台机器能干多重的活&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;操作系统&lt;/td&gt;
&lt;td&gt;你熟悉的 Linux（Ubuntu、Alibaba Cloud Linux、CentOS 等）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;服务软件&lt;/td&gt;
&lt;td&gt;提供业务能力的程序：Nginx、MySQL、你的 Go 后端&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IP / 端口 / 域名&lt;/td&gt;
&lt;td&gt;IP 定位机器、端口定位机器上的程序、域名给人好记&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="2-区别云服务器-vs-虚拟机开启服务器端"&gt;2. 区别：云服务器 vs 虚拟机「开启服务器端」&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：技术层面你几乎不换思路——都是「Linux + 服务程序」。真正的差别在 4 件事：&lt;strong&gt;谁能访问、关机了怎么办、坏了谁来修、按什么计费&lt;/strong&gt;。&lt;/p&gt;</description></item></channel></rss>