<?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>Go on 鹿鸣青野的blog</title><link>https://www.sylgalaxy.xyz/tags/go/</link><description>Recent content in Go 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/tags/go/index.xml" rel="self" type="application/rss+xml"/><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>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>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>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>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>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>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>包与导入</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>反射（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>云服务器认识与使用：从虚拟机到公网部署</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>