Go语言的map

一、map 是什么?

map 是 Go 里 键值对(key-value) 的集合,类似:

  • Java 的 HashMap

  • Python 的 dict

Go 复制代码
map[KeyType]ValueType

特点:

无序、引用类型、key 唯一、查找快

二、map 的基本使用

1. 声明 & 初始化

Go 复制代码
// 声明但未初始化(nil map)
var m map[string]int

// 初始化(推荐)
m = make(map[string]int)

// 声明 + 初始化
m := make(map[string]int)

// 带初始值
m := map[string]int{
    "java":  8,
    "go":    3,
    "python": 5,
}

注意:下面的写法会报错:

Go 复制代码
var m map[string]int
m["a"] = 1   // ❌ panic:assignment to entry in nil map

map 用之前 必须 make 或字面量初始化

2. map的读 / 写 / 删

Go 复制代码
m["go"] = 10          // 写
v := m["go"]          // 读
delete(m, "redis")    // 删除

3. 判断 key 是否存在

Go 复制代码
v, ok := m["python"]
if ok {
    fmt.Println("存在", v)
} else {
    fmt.Println("不存在")
}

如果 key 不存在:

  • vvalue 类型的零值

  • ok == false

三、map 的遍历

Go 复制代码
for k, v := range m {
    fmt.Println(k, v)
}

注意

  • 遍历顺序 每次都可能不一样

  • Go 故意打乱顺序,避免依赖顺序写代码

如果需要顺序:

单独维护一个 slice 存 key

四、map 的 key / value 有哪些限制?

1. key 必须是 可比较类型

以下可以用作key:

  • int

  • string

  • bool

  • 指针

  • 数组

  • struct(前提:字段都可比较)

以下 不可以用作key:

  • slice

  • map

  • function

2 value 没限制

Go 复制代码
map[string][]int
map[string]map[string]int
map[string]interface{}

五、map 是引用类型

Go 复制代码
func modify(m map[string]int) {
    m["go"] = 100
}

func main() {
    m := map[string]int{"go": 10}
    modify(m)
    fmt.Println(m["go"]) // 100
}

将map作为参数传入map,vaule不会发生改变,是因为:

  • map 底层是 指针结构

  • 函数传参不会拷贝整个 map

六、并发安全问题

map 不是并发安全的,使用不当会报以下错误:

fatal error: concurrent map writes

可以使用以下方式来实现并发安全

1.加锁(最常用)

Go 复制代码
var m = make(map[string]int)
var mu sync.Mutex

mu.Lock()
m["a"] = 1
mu.Unlock()
  1. 使用 sync.Map(读多写少)
Go 复制代码
var m sync.Map
m.Store("a", 1)
v, ok := m.Load("a")

3.channel 串行化访问

七、map 的一些常见坑

  1. 不能直接取地址
Go 复制代码
v := m["go"]
// &m["go"]  不允许

因为 map 在扩容时,地址会变化

  1. 不能比较 map
Go 复制代码
m1 == m2   //  编译错误

只能和 nil 比较:

Go 复制代码
if m == nil {}

3. map 扩容会导致性能抖动

可以提前分配容量:

Go 复制代码
m := make(map[string]int, 10000)

八、和 Java HashMap 的对比

维度 Go map Java HashMap
是否有序 ❌ 无序 ❌ 无序
是否线程安全
初始化 make / 字面量 new HashMap
判断存在 v, ok := m[k] containsKey()
nil 行为 写会 panic put 会 NPE
泛型 原生支持 Java 8+

九、典型使用场景

  • 缓存 / 去重

  • 计数器(词频统计)

  • ID → 对象 映射

  • 配置表

  • JSON 反序列化动态字段

Go 复制代码
count := make(map[string]int)
for _, w := range words {
    count[w]++
}

十、总结

Go 的 map = 高性能、语法极简,但对并发和顺序非常"严格"的 HashMap

相关推荐
Lee川13 小时前
mini-cursor 揭秘:从 Tool 定义到 Agent 循环的完整实现
前端·人工智能·后端
kkeeper~14 小时前
0基础C语言积跬步之深入理解指针(5下)
c语言·开发语言
一直不明飞行14 小时前
Java的equals(),hashCode()应该在什么时候重写
java·开发语言·jvm
盲敲代码的阿豪14 小时前
Python 入门基础教程(爬虫前置版)
开发语言·爬虫·python
basketball61615 小时前
C++ 构造函数完全指南:从入门到进阶
java·开发语言·c++
互联科技报15 小时前
2026超融合选型:Top5品牌与市场格局解读
开发语言·perl
weixin1997010801615 小时前
[特殊字符] 智能数据采集:数字化转型的“数据石油勘探队”(附Python实战源码)
开发语言·python
星浩AI15 小时前
OpenHuman 对比 OpenClaw、Hermes Agent
人工智能·后端·agent
想唱rap15 小时前
IO多路转接之poll
服务器·开发语言·数据库·c++
小江的记录本15 小时前
【Java基础】泛型:泛型擦除、通配符、上下界限定(附《思维导图》+《面试高频考点清单》)
java·数据结构·后端·mysql·spring·面试·职场和发展