📏长度是类型的一部分
[3]int ≠ [4]int。
不可互赋 / 比较 / 作同型参数。
💾值类型
赋值与传参 = 整体拷贝,
函数内改副本不影响原数组。
💥越界即 panic
下标限定 0 ~ len-1,
超范围运行时崩溃。
补零值(int=0 / string="" / bool=false)· 同长同型才可 == · [...]int{1,2,3} 推断长度 · [5]int{2:100} 下标赋值
💡 常见疑问:数组与切片声明差在哪?
数组定长、值类型、长度属类型;切片动态、引用、共享底层数组。声明:var a [3]int(零值数组)/ var s []int(nil 切片)/ s := []int{}(空切片)/ make([]int,3,5)(指定 len·cap)。
切片头只存指针 / 长度 / 容量,数据在底层数组。由同一数组切出的子切片共享该数组。
⚠ 两者 ptr 指向同一底层数组 → sub[0]=9 时,s 也变成 [9 2 3]
引用语义:只存头,不存数据append:容量够原地写,不够才扩容copy:深拷贝,断绝共享
💡 常见疑问:为什么 int 后面要加 {}?
[]int 只是类型名;加 {} 才是复合字面量——当场造出值。空 {} = 创建但无元素。数组 / Map / 结构体同理。
💡 常见疑问:切片类型只能是 []int 吗?
切片类型 = [] + 元素类型:[]int/[]string/[]float64 互不相同。长度不参与类型——这是与数组最大区别。
nil 切片 · var s []int
s == nil ✓
底层数组无
JSON 序列化null
可读 / append可
空切片 · s := []int{}
s == nil ✗
底层数组有(空)
JSON 序列化[]
可读 / append可
要点:两者均可读、可 append、可 range;差异仅在 ==nil 判断与 JSON 输出。下标写入二者都越界 panic——「不可写」形容的是 nil map,非切片。
哈希表引用类型无序:遍历顺序随机delete / len
⚠ nil map 写入即 panic:须先 make 或字面量初始化,否则 m[k]=v 崩溃。
v := m[k]
→
不存在也返回零值
→
v, ok := m[k]
ok = truekey 真实存在,v 即其值(含零值情形)
ok = falsekey 不存在,v 是零值兜底
通用惯用法 value, ok := 亦见于类型断言 i.(T) 与 channel 接收 <-ch
💾
值类型
赋值 / 传参整体拷贝;大结构体建议传 *T。
⚖️
可比较有条件
所有字段可比时才能 ==;含 slice / map 字段则不可比。
🧩
嵌入组合
匿名嵌套自动提升字段与方法,实现「组合优于继承」。
🏷️
tag 元信息
`json:"name"` 供反射 / 序列化读取,不影响运行时。
💾
数组传参被拷
现象:函数内改不动原数组。
根因:值类型整体拷贝。
规避:传 *[N]T 或改用切片。
🔗
切片共享污染
现象:改子切片连累原切片。
根因:共享底层数组。
规避:独立时用 copy 或触发扩容。
🗺️
nil map 写入
现象:panic。
根因:未初始化。
规避:先 make 或字面量。
四类型对比速查
| 维度 | 数组 | 切片 | Map | 结构体 |
| 语义 | 值类型 | 引用 | 引用 | 值类型 |
| 长度 | 固定·属类型 | 动态 | 动态 | 字段固定 |
| 可比 == | 同长同型 | 仅 nil | 仅 nil | 字段全可比 |
| 零值 | 全零数组 | nil | nil | 字段全零 |
| 传参开销 | 整体(大) | 仅头 | 仅头 | 整体(大→指针) |
| 日常定位 | 少用 | 最常用 | KV 查询 | 建模实体 |
自测 3 题
Q1
var a [3]int
var b [4]int
a = b 能编译?
查看解析
不能。长度不同即类型不同,Go 禁止跨类型赋值。
Q2
a:=[]int{1,2,3}
b:=a[:2]
b[0]=9
a 变成?
查看解析
[9 2 3]。b 与 a 共享底层数组,改 b[0] 即改底层元素。
Q3
var m map[int]int
m[1]=10 会?
查看解析
panic(向 nil map 写入)。修复:make 或字面量初始化。