<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Map on Chen Shungen</title><link>https://chenshungen.cn/tags/map/</link><description>Recent content in Map on Chen Shungen</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Mon, 20 Apr 2026 12:00:00 +0800</lastBuildDate><atom:link href="https://chenshungen.cn/tags/map/index.xml" rel="self" type="application/rss+xml"/><item><title>Go 并发原语 - Map</title><link>https://chenshungen.cn/blog/golang-concurrency/golang-map/</link><pubDate>Mon, 20 Apr 2026 12:00:00 +0800</pubDate><guid>https://chenshungen.cn/blog/golang-concurrency/golang-map/</guid><description>&lt;p>前面几篇我们聊了各种同步原语，这一篇聊一个更贴近日常开发的话题——&lt;strong>map 的并发安全&lt;/strong>。Go 内建的 map 类型不是线程安全的，并发读写会直接 panic。那怎么办？这一篇我们从内建 map 的基本用法和陷阱开始，逐步讲到加锁方案和标准库的 &lt;code>sync.Map&lt;/code>。&lt;/p>
&lt;h2 id="一内建-map-基本用法">一、内建 map 基本用法&lt;/h2>
&lt;p>Go 的 map 是内建的哈希表类型：&lt;/p>
&lt;div class="highlight-wrapper">
 &lt;button class="copy-code-btn" type="button" aria-label="Copy code to clipboard">
 &lt;svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
 &lt;rect x="9" y="9" width="13" height="13" rx="2" ry="2">&lt;/rect>
 &lt;path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">&lt;/path>
 &lt;/svg>
 &lt;span class="copy-text">Copy&lt;/span>
 &lt;/button>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-go" data-lang="go">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">m&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nb">make&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kd">map&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="kt">string&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">m&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s">&amp;#34;age&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="mi">28&lt;/span> &lt;span class="c1">// 写入&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">v&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">m&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s">&amp;#34;age&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">// 读取&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">v&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">ok&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="nx">m&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1">// 读取 + 检查是否存在&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">delete&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;age&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">// 删除&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>
&lt;p>key 的类型必须是 &lt;strong>可比较的（comparable）&lt;/strong>——能用 &lt;code>==&lt;/code> 和 &lt;code>!=&lt;/code> 比较：&lt;/p>
&lt;div class="highlight-wrapper">
 &lt;button class="copy-code-btn" type="button" aria-label="Copy code to clipboard">
 &lt;svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
 &lt;rect x="9" y="9" width="13" height="13" rx="2" ry="2">&lt;/rect>
 &lt;path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">&lt;/path>
 &lt;/svg>
 &lt;span class="copy-text">Copy&lt;/span>
 &lt;/button>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">┌──────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ✅ 可以做 key 的类型 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├──────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ bool、整数、浮点数、复数、字符串 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 指针、Channel、接口 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 所有字段都可比较的 struct │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ 元素都可比较的数组 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├──────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ❌ 不能做 key 的类型 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├──────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ slice、map、函数 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└──────────────────────────────────────────────────────────┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>
&lt;h3 id="struct-做-key-的坑">struct 做 key 的坑&lt;/h3>
&lt;p>用 struct 做 key 时要特别小心——修改了 struct 字段后，就再也找不到原来的值了：&lt;/p></description></item></channel></rss>