Go 语言中的 Slice 类型

Slice(切片)是 Go 语言内置的可变长度序列,属于引用类型,基于底层数组封装实现,解决数组长度固定、数组传参完整拷贝开销大的问题,是 Go 开发最常用的数据结构之一。 1. Slice 的基础特性 可变长度:长度不固定,可通过 append 动态追加元素。 底层数组共享:切片本身不存储实际元素,元素存放在底层数组;多个切片可以指向同一个底层数组,修改会互相影响。 len 与 cap 分离:len代表切片当前可用元素个数;cap代表底层数组允许的最大容量。 零值特性:切片零值为 nil,nil slice len=0、cap=0;nil slice 和空切片 []int{} 不相等。 引用语义:切片变量存储的是结构体头信息,赋值、传参拷贝的是切片头,不是底层数组。 不可直接比较:切片不能使用 == 判断两个切片内容是否相等,仅允许和 nil 做相等判断。 友情提示 上述特性与 Slice 的底层实现紧密关联,建议结合第 4 节"Slice 底层实现原理"章节阅读,以获得更深入的理解。 2. Slice 的四种初始化方式 切片必须初始化,nil切片可以读取、append,但不能直接对索引位置赋值。 2.1 声明未初始化(nil slice) 仅定义变量,底层数组指针为 nil,len=0、cap=0。 // 声明nil切片,未分配底层数组 var a []string fmt.Println(a == nil) // true fmt.Println(len(a), cap(a)) // 0 0 // a[0] = "hello" // 未初始化的切片直接赋值会引发 panic // panic: index out of range 2.2 字面量初始化(空切片/带初始值) 直接初始化,分配底层数组,支持空切片和预设元素。 ...

Go 语言中的 Map 类型

Map 是 Go 语言内置的键值对(key-value)哈希集合,属于引用类型,核心作用是通过唯一键快速索引对应值,查询、插入、删除的平均时间复杂度均为O(1),是 Go 开发中最常用的数据结构之一。 1. Map 的基础特性 键唯一性:同一个 Map 中,key 唯一,重复插入会覆盖旧值。 键类型限制:key 必须是可比较类型(int、string、bool、结构体等),切片、map、函数不可作为 key。 无序性:Map 不存储键值对插入顺序,遍历顺序随机(Go 1.12+ 每次遍历顺序不一致)。 零值特性:Map 零值为 nil,nil map 无法写入数据,仅可读取。 引用类型:赋值、传参仅传递引用,多个变量指向同一个底层数据 2. Map 的四种初始化方式 Go 语言 Map 必须初始化后才能写入数据,未初始化的nil map直接写入会触发运行时 panic。以下是所有合法初始化方式。 2.1 声明未初始化(nil map) 仅定义变量,未分配内存,零值为nil,只能读、不能写。 package main import "fmt" func main() { // 声明nil map,未初始化 var m map[string]int fmt.Println(m == nil) // 输出:true // m["a"] = 1 // 报错:panic: assignment to entry in nil map } 2.2 字面量初始化(空 Map/带初始值) 直接初始化并分配内存,支持空 Map 和预设键值对,最常用。 ...

Go 语言中的字符串类型

Go 原生支持字符串类型,关键字string用于表示字符串数据类型。 1. 底层实现 Go 中的string实际上是一个struct类型,其本身并不真正存储字符串数据,仅是由一个指向底层数组的指针和字符串的长度字段组成,可以在标准库的reflect包中,找到下面代码: // $GOROOT/src/reflect/value.go // StringHeader是一个string的运行时表示 type StringHeader struct { Data uintptr Len int } 由于string类型实际上只是一个对底层存储的引用,因此实际传参的开销非常小,另外在生成string变量时,会同时存储字节长度len,所以无论字符串长度怎么变化,获取长度的时间都是O(1)。 底层实现图解: 三个必须记住的特性: 特性 含义 不可变 任何“修改”操作都会产生新字符串,原串不变 UTF-8 编码 源码中的字符串字面量默认是 UTF-8 零值是 "" 不是 nil,var s string 是空串 var s string = "Hello" // s[0] = 'h' // 编译错误:cannot assign to s[0] b := []byte(s) // 想修改就转成切片(会复制一份) 注意:len(s)返回的是字节数,不是字符数。中文、emoji 等多字节字符会让两者不相等。 2. 字面量与引号 Go 中初始化字符串变量,需要在双引号"中定义值,单引号'用于单个字符( 以及 runes )。 var Name string = "zhangsan" age := "18" var a char = 'a' s1 := "hello\nworld" // 双引号:支持 \n \t \" \\ 等转义 // 输出: // hello // world s2 := `hello\nworld` // 反引号(原生字符串):原样保留 // 输出: // hello\nworld s3 := "" // 空串,len == 0 Go 中没有也不支持三引号的写法,使用反引号来表示原生字面量。由于所见即所得,原样保留,可跨行的特点,常用于SQL/JSON/正则表达式中 ...