<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>编译器优化 on Zampo Blog</title><link>https://blog.cpdd.fyi/tags/%E7%BC%96%E8%AF%91%E5%99%A8%E4%BC%98%E5%8C%96/</link><description>Recent content in 编译器优化 on Zampo Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sat, 23 May 2026 11:55:00 +0800</lastBuildDate><atom:link href="https://blog.cpdd.fyi/tags/%E7%BC%96%E8%AF%91%E5%99%A8%E4%BC%98%E5%8C%96/index.xml" rel="self" type="application/rss+xml"/><item><title>Go 数组为什么这么硬？因为它要把边界写进类型里</title><link>https://blog.cpdd.fyi/posts/go-array-design/</link><pubDate>Sat, 23 May 2026 11:55:00 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/go-array-design/</guid><description>&lt;p&gt;同样是复制，一个 &lt;code&gt;[32]byte&lt;/code&gt; 的 hash 往往很安全，一个 struct 里的 &lt;code&gt;[4096]int&lt;/code&gt; 却可能把性能拖得很难看。&lt;/p&gt;
&lt;p&gt;这不是 Go 数组“好不好用”的问题，而是你有没有把它当成正确的东西。&lt;/p&gt;
&lt;p&gt;很多 Go 开发者平时几乎不直接写数组。业务列表用 slice，字典用 map，缓冲区也经常一上来就是 &lt;code&gt;[]byte&lt;/code&gt;。于是数组很容易被误解成 slice 背后的旧零件：知道有这么个东西，但最好别碰。&lt;/p&gt;
&lt;p&gt;这个判断太粗了。&lt;/p&gt;
&lt;p&gt;数组在 Go 里不是为了替代 slice 做动态集合。它的价值恰恰在于“不灵活”：长度固定、类型固定、赋值复制、元素可比较时整体可比较。它把一块数据的形状写死，让函数边界、类型系统和编译器都少猜一点。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cpdd.fyi/images/go-array-design/cover.png" alt="Go 数组的确定形状"&gt;&lt;/p&gt;
&lt;h2 id="数组是值长度是类型"&gt;数组是值，长度是类型&lt;/h2&gt;
&lt;p&gt;Go 的数组变量代表整个数组，不是指向第一个元素的地址。&lt;/p&gt;
&lt;p&gt;这句话听起来像语法点，实际影响很大。你把一个数组赋给另一个变量，复制的是整个数组；你把数组传给函数，函数收到的也是一份数组值。除非你显式传 &lt;code&gt;*[N]T&lt;/code&gt;，否则函数里改不到调用方那份数组。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ValueSemantics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;copyOfOriginal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;copyOfOriginal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;copyOfOriginal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;返回的第一份还是 &lt;code&gt;[1 2 3]&lt;/code&gt;，第二份才是 &lt;code&gt;[99 2 3]&lt;/code&gt;。&lt;/p&gt;</description></item></channel></rss>