<?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>类型 on 维克的博客</title><link>https://blogs.wuvikr.top/tags/%E7%B1%BB%E5%9E%8B/</link><description>Recent content in 类型 on 维克的博客</description><generator>Hugo</generator><language>en</language><lastBuildDate>Wed, 30 Sep 2026 15:55:22 +0800</lastBuildDate><atom:link href="https://blogs.wuvikr.top/tags/%E7%B1%BB%E5%9E%8B/index.xml" rel="self" type="application/rss+xml"/><item><title>Go 语言中的 Slice 类型</title><link>https://blogs.wuvikr.top/posts/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84slice%E7%B1%BB%E5%9E%8B/</link><pubDate>Wed, 30 Sep 2026 15:55:22 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84slice%E7%B1%BB%E5%9E%8B/</guid><description>&lt;p>Slice（切片）是 Go 语言内置的&lt;strong>可变长度序列&lt;/strong>，属于引用类型，基于底层数组封装实现，&lt;strong>解决数组长度固定、数组传参完整拷贝开销大的问题&lt;/strong>，是 Go 开发最常用的数据结构之一。&lt;/p>
&lt;h1 id="1-slice-的基础特性">1. Slice 的基础特性&lt;/h1>
&lt;ul>
&lt;li>&lt;strong>可变长度&lt;/strong>：长度不固定，可通过 &lt;code>append&lt;/code> 动态追加元素。&lt;/li>
&lt;li>&lt;strong>底层数组共享&lt;/strong>：切片本身不存储实际元素，元素存放在底层数组；多个切片可以指向同一个底层数组，修改会互相影响。&lt;/li>
&lt;li>&lt;strong>len 与 cap 分离&lt;/strong>：&lt;code>len&lt;/code>代表切片当前可用元素个数；&lt;code>cap&lt;/code>代表底层数组允许的最大容量。&lt;/li>
&lt;li>&lt;strong>零值特性&lt;/strong>：切片零值为 &lt;code>nil&lt;/code>，&lt;code>nil slice&lt;/code> len=0、cap=0；&lt;code>nil slice&lt;/code> 和空切片 &lt;code>[]int{}&lt;/code> 不相等。&lt;/li>
&lt;li>&lt;strong>引用语义&lt;/strong>：切片变量存储的是结构体头信息，赋值、传参拷贝的是切片头，不是底层数组。&lt;/li>
&lt;li>&lt;strong>不可直接比较&lt;/strong>：切片不能使用 &lt;code>==&lt;/code> 判断两个切片内容是否相等，仅允许和 &lt;code>nil&lt;/code> 做相等判断。&lt;/li>
&lt;/ul>
&lt;div class="alert alert-tip" role="alert">
&lt;p class="alert-title">友情提示&lt;/p>
&lt;p>上述特性与 Slice 的底层实现紧密关联，建议结合第 4 节&amp;quot;Slice 底层实现原理&amp;quot;章节阅读，以获得更深入的理解。&lt;/p>
&lt;/div>
&lt;h1 id="2-slice-的四种初始化方式">2. Slice 的四种初始化方式&lt;/h1>
&lt;p>切片必须初始化，&lt;code>nil&lt;/code>切片可以读取、append，但不能直接对索引位置赋值。&lt;/p>
&lt;h2 id="21-声明未初始化nil-slice">2.1 声明未初始化（nil slice）&lt;/h2>
&lt;p>仅定义变量，底层数组指针为 nil，len=0、cap=0。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 声明nil切片，未分配底层数组&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">a&lt;/span> []&lt;span style="color:#66d9ef">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">a&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>) &lt;span style="color:#75715e">// true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(len(&lt;span style="color:#a6e22e">a&lt;/span>), cap(&lt;span style="color:#a6e22e">a&lt;/span>)) &lt;span style="color:#75715e">// 0 0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// a[0] = &amp;#34;hello&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 未初始化的切片直接赋值会引发 panic&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// panic: index out of range&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="22-字面量初始化空切片带初始值">2.2 字面量初始化（空切片/带初始值）&lt;/h2>
&lt;p>直接初始化，分配底层数组，支持空切片和预设元素。&lt;/p></description></item><item><title>Go 语言中的 Map 类型</title><link>https://blogs.wuvikr.top/posts/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84map%E7%B1%BB%E5%9E%8B/</link><pubDate>Mon, 28 Sep 2026 13:01:24 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84map%E7%B1%BB%E5%9E%8B/</guid><description>&lt;p>Map 是 Go 语言内置的&lt;strong>键值对（key-value）哈希集合&lt;/strong>，属于引用类型，核心作用是通过唯一键快速索引对应值，查询、插入、删除的平均时间复杂度均为&lt;code>O(1)&lt;/code>，是 Go 开发中最常用的数据结构之一。&lt;/p>
&lt;h1 id="1-map-的基础特性">1. Map 的基础特性&lt;/h1>
&lt;ul>
&lt;li>&lt;strong>键唯一性&lt;/strong>：同一个 Map 中，key 唯一，重复插入会覆盖旧值。&lt;/li>
&lt;li>&lt;strong>键类型限制&lt;/strong>：key 必须是&lt;strong>可比较类型&lt;/strong>（int、string、bool、结构体等），切片、map、函数不可作为 key。&lt;/li>
&lt;li>&lt;strong>无序性&lt;/strong>：Map 不存储键值对插入顺序，遍历顺序随机（Go 1.12+ 每次遍历顺序不一致）。&lt;/li>
&lt;li>&lt;strong>零值特性&lt;/strong>：Map 零值为 &lt;code>nil&lt;/code>，&lt;code>nil map&lt;/code> 无法写入数据，仅可读取。&lt;/li>
&lt;li>&lt;strong>引用类型&lt;/strong>：赋值、传参仅传递引用，多个变量指向同一个底层数据&lt;/li>
&lt;/ul>
&lt;h1 id="2-map-的四种初始化方式">2. Map 的四种初始化方式&lt;/h1>
&lt;p>Go 语言 Map 必须初始化后才能写入数据，未初始化的&lt;code>nil map&lt;/code>直接写入会触发运行时 panic。以下是所有合法初始化方式。&lt;/p>
&lt;h2 id="21-声明未初始化nil-map">2.1 声明未初始化（&lt;code>nil map&lt;/code>）&lt;/h2>
&lt;p>仅定义变量，未分配内存，零值为&lt;code>nil&lt;/code>，只能读、不能写。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 声明nil map，未初始化&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>) &lt;span style="color:#75715e">// 输出：true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// m[&amp;#34;a&amp;#34;] = 1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 报错：panic: assignment to entry in nil map&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="22-字面量初始化空-map带初始值">2.2 字面量初始化（空 Map/带初始值）&lt;/h2>
&lt;p>直接初始化并分配内存，支持空 Map 和预设键值对，最常用。&lt;/p></description></item><item><title>Go 语言中的字符串类型</title><link>https://blogs.wuvikr.top/posts/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%B1%BB%E5%9E%8B/</link><pubDate>Fri, 25 Sep 2026 10:01:44 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%B1%BB%E5%9E%8B/</guid><description>&lt;p>Go 原生支持字符串类型，关键字&lt;code>string&lt;/code>用于表示字符串数据类型。&lt;/p>
&lt;h1 id="1-底层实现">1. 底层实现&lt;/h1>
&lt;p>Go 中的&lt;code>string&lt;/code>实际上是一个&lt;code>struct&lt;/code>类型，其本身并不真正存储字符串数据，仅是由一个指向底层数组的指针和字符串的长度字段组成，可以在标准库的&lt;code>reflect&lt;/code>包中，找到下面代码：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// $GOROOT/src/reflect/value.go&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// StringHeader是一个string的运行时表示&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">StringHeader&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Data&lt;/span> &lt;span style="color:#66d9ef">uintptr&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Len&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>由于&lt;code>string&lt;/code>类型实际上只是一个对底层存储的引用，因此实际传参的开销非常小，另外在生成&lt;code>string&lt;/code>变量时，会同时存储字节长度&lt;code>len&lt;/code>，所以无论字符串长度怎么变化，获取长度的时间都是&lt;code>O(1)&lt;/code>。&lt;/p>
&lt;p>&lt;strong>底层实现图解&lt;/strong>：&lt;/p>
&lt;p>&lt;img alt="string的底层实现" loading="lazy" src="https://blogs.wuvikr.top/posts/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%B1%BB%E5%9E%8B/string%E7%9A%84%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0.png">&lt;/p>
&lt;p>&lt;strong>三个必须记住的特性&lt;/strong>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特性&lt;/th>
&lt;th>含义&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>不可变&lt;/td>
&lt;td>任何“修改”操作都会产生新字符串，原串不变&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>UTF-8 编码&lt;/td>
&lt;td>源码中的字符串字面量默认是 UTF-8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>零值是 &lt;code>&amp;quot;&amp;quot;&lt;/code>&lt;/td>
&lt;td>不是 nil，&lt;code>var s string&lt;/code> 是空串&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// s[0] = &amp;#39;h&amp;#39; // 编译错误：cannot assign to s[0]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> []byte(&lt;span style="color:#a6e22e">s&lt;/span>) &lt;span style="color:#75715e">// 想修改就转成切片（会复制一份）&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;blockquote>
&lt;p>注意：&lt;code>len(s)&lt;/code>返回的是字节数，不是字符数。中文、emoji 等多字节字符会让两者不相等。&lt;/p>
&lt;/blockquote>
&lt;h1 id="2-字面量与引号">2. 字面量与引号&lt;/h1>
&lt;p>Go 中初始化字符串变量，需要在双引号&lt;code>&amp;quot;&lt;/code>中定义值，单引号&lt;code>'&lt;/code>用于单个字符（ 以及 runes ）。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">Name&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;zhangsan&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">age&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;18&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">a&lt;/span> &lt;span style="color:#a6e22e">char&lt;/span> = &lt;span style="color:#e6db74">&amp;#39;a&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">s1&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;hello\nworld&amp;#34;&lt;/span> &lt;span style="color:#75715e">// 双引号：支持 \n \t \&amp;#34; \\ 等转义&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 输出：&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// hello&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// world&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">s2&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">`hello\nworld`&lt;/span> &lt;span style="color:#75715e">// 反引号（原生字符串）：原样保留&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 输出：&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// hello\nworld&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">s3&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#75715e">// 空串，len == 0&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Go 中没有也不支持三引号的写法，使用反引号来表示原生字面量。由于所见即所得，原样保留，可跨行的特点，常用于&lt;code>SQL/JSON/正则表达式&lt;/code>中&lt;/p></description></item></channel></rss>