Map(哈希表)
Go 的内置关联容器,键值对存储,底层是哈希表 一、概述 map 是 Go 的内置数据结构,用于存储键值对。它等价于 C++ 的 std::unordered_map——基于哈希表实现,不是红黑树(Go 没有 std::map 那样的有序容器)。 核心特性: 引用类型,赋值和传参共享底层数组 键必须支持 == 比较(可哈希) 遍历顺序不确定(哈希表特性) 并发读写会触发 fatal(不是 data race,直接崩程序) 二、C++ 对照速查表 Go C++ 说明 map[K]V 类型声明 std::unordered_map<K,V> 类型声明 声明一个 map 类型 m := map[string]int{} auto m = unordered_map<string,int>(); 字面量初始化 m := make(map[string]int) auto m = unordered_map<string,int>(); make 初始化 m := make(map[string]int, 64) auto m = unordered_map<string,int>(64); 预分配容量 m["key"] = 42 m["key"] = 42; 插入/修改 delete(m, "key") m.erase("key"); 删除键 val, ok := m["key"] auto it = m.find("key"); it != m.end() 查找(双返回值) len(m) m.size() 获取大小 nil map nullptr 的 map 未初始化的 map for k, v := range m for (auto& [k, v] : m) 遍历 无 std::map<K,V> Go 没有有序 map 三、声明与初始化 3.1 字面量初始化(最常用) package main import "fmt" func main() { // 字面量初始化:声明 + 赋值一步到位 ages := map[string]int{ "Alice": 30, "Bob": 25, "Carol": 28, } fmt.Println(ages) // map[Alice:30 Bob:25 Carol:28] // 空 map empty := map[string]int{} fmt.Println(len(empty)) // 0 } 3.2 make 初始化 // make 创建空 map,可选预分配容量(提高性能) scores := make(map[string]int) // 零值容量 scores2 := make(map[string]int, 64) // 预分配 64 个槽位 // 适用场景:已知大致大小,预分配可减少扩容次数 users := make(map[int]string, 1000) 3.3 nil map(未初始化) var m map[string]int // nil map,值为 nil fmt.Println(m) // map[] fmt.Println(len(m)) // 0 — len 对 nil map 返回 0 3.4 C++ 对照 Go C++ ages := map[string]int{"Alice": 30} auto ages = unordered_map<string,int>{{"Alice", 30}}; m := make(map[string]int) auto m = unordered_map<string,int>(); m := make(map[string]int, 64) auto m = unordered_map<string,int>(64); var m map[string]int (nil) unordered_map<string,int>* m = nullptr; 四、增删改查 4.1 增 / 改(赋值) m := map[string]int{} // 不存在的 key → 插入 m["apple"] = 5 m["banana"] = 3 // 已存在的 key → 修改 m["apple"] = 10 fmt.Println(m) // map[apple:10 banana:3] 4.2 查(双返回值 ok 模式) m := map[string]int{"x": 1, "y": 2} // 双返回值:值 + 是否存在(ok 模式) val, ok := m["x"] fmt.Println(val, ok) // 1 true val2, ok2 := m["z"] fmt.Println(val2, ok2) // 0 false(零值,不存在) // C++ 对比: // auto it = m.find("x"); // if (it != m.end()) { /* 找到 */ } 为什么需要 ok 模式? 如果值类型是 int,零值是 0,无法区分"值为 0"和"不存在"。ok 布尔值解决了这个问题。 ...
豫公网安备41108202000982号