Golang中的map的key可以是哪些类型?可以嵌套map吗?
map[Key]Value
Key 必须是可比较的类型 :只有支持 == 和 != 操作符的类型才能作为 map 的 Key
1. 哪些类型可以作为 Map 的 Key?
✅ 合法的 Key 类型(可比较)
- 基本数据类型:
bool、int(及其各种变体如int8、uint64等)、float32、float64、complex、string - 指针类型(Pointer): 指向同一内存地址的指针是相等的
- 通道类型(Channel): 使用
make创建的同一个 channel 是相等的 - 接口类型(Interface): 前提是接口所绑定的动态类型本身是可比较的(如果在运行时绑定了不可比较的类型,会引发 panic)
- 数组(Array): 前提是数组内部的元素类型是可比较的(注意:数组是定长的,如
[3]int) - 结构体(Struct): 前提是结构体内部的所有字段都是可比较的类型
❌ 非法的 Key 类型(不可比较)
- 切片(Slice):
[]T(因为切片的底层是指针、长度和容量,它的内容随时可能变化,比较它们没有意义且容易出错) - 映射(Map):
map[K]V - 函数(Func):
func()
2. 可以嵌套 Map 吗?
完全可以。 map 的 Value 可以是任何类型,当然也包括另一个 map。
⚠️ 嵌套 Map 的致命易错点: 外层 map 初始化后,如果直接对内层 map 赋值,会引发 panic: assignment to entry in nil map。内层 map 在使用前必须单独被初始化。
代码演示👀
1. String 作为 key
go
strMap := map[string]int{"Alice": 90, "Bob": 85}
fmt.Println(strMap) // map[Alice:90 Bob:85]
2. Struct 作为 key (非常实用,常用于坐标或复合主键)
go
type Point struct {
X int
Y int
}
pointMap := map[Point]string{
{X: 0, Y: 0}: "Origin",
{X: 1, Y: 2}: "Point A",
}
fmt.Println(pointMap) // map[{0 0}:Origin {1 2}:Point A]
fmt.Println("坐标 (1,2) 对应的是:", pointMap[Point{1, 2}]) // Point A
3. Array 作为 key (注意是数组 [3]int,不是切片 []int)
go
arrayMap := map[[3]int]string{
{1, 2, 3}: "Sequence One",
}
fmt.Println(arrayMap) // map[[1 2 3]:Sequence One]
sliceMap := map[[]int]string{}
fmt.Println(sliceMap) // invalid map key type []int
嵌套 Map 及其正确初始化方式
go
// 定义一个嵌套 Map:外层 key 是班级(string),内层是 学生姓名(string) -> 分数(int)
nestedMap := make(map[string]map[string]int)
nestedMap["ClassA"]["Alice"] = 95 // 【错误写法】 panic: assignment to entry in nil map
// 必须先初始化内层的 Map
nestedMap["ClassA"] = make(map[string]int)
// 向内层 Map 添加数据了
nestedMap["ClassA"]["Alice"] = 95
nestedMap["ClassA"]["Bob"] = 88
// 再加一个班级
nestedMap["ClassB"] = make(map[string]int)
nestedMap["ClassB"]["Charlie"] = 70
fmt.Println("Nested Map 全貌:", nestedMap) // map[ClassA:map[Alice:95 Bob:88] ClassB:map[Charlie:70]]
fmt.Println("ClassA 中 Alice 的分数:", nestedMap["ClassA"]["Alice"]) // Alice 的分数: 95