Go语言map是无序键值对集合,需声明后make初始化;键必须支持==比较(如string、int),不可用切片、map或函数;遍历顺序随机,线程不安全,nil map读写会panic。

Go语言中的map是无序的键值对集合,必须先声明再使用(不能像切片那样直接字面量赋值给未声明变量),且键类型必须支持==比较(如string、int、bool、指针等,但不能是切片、map或函数)。
创建Map:三种常用方式
推荐显式初始化,避免nil map导致运行时panic:
-
声明+make初始化(最常用):
ages := make(map[string]int) -
字面量初始化(带初始值):
colors := map[string]string{"red": "#ff0000", "blue": "#0000ff"} -
声明后赋值(不推荐用于空map):
var scores map[string]int
scores = make(map[string]int) // 必须make,否则为nil
访问和修改Map元素
通过键名访问值,语法简洁,但需注意“不存在的键”会返回零值,不报错:
-
读取值:
age := ages["Alice"]→ 若"Alice"不存在,age为0(int零值) -
安全读取(判断是否存在):
if age, ok := ages["Bob"]; ok { fmt.Println("Bob is", age) }
其中ok为bool,仅当键存在时为true -
添加/更新元素:
ages["Charlie"] = 30(键存在则覆盖,不存在则插入) -
删除元素:
delete(ages, "Alice")(删除不存在的键无副作用)
遍历Map:用for-range,顺序不保证
Go中map遍历顺序是随机的(每次运行可能不同),如需固定顺序,需额外排序键:
立即学习“go语言免费学习笔记(深入)”;
-
基础遍历(键+值):
for name, age := range ages { fmt.Printf("%s: %d\n", name, age) } -
只遍历键:
for name := range ages { fmt.Println(name) } -
只遍历值:
for _, age := range ages { fmt.Println(age) }(用_忽略键) -
按字母序遍历(需先收集并排序键):
var keys []string
for k := range ages { keys = append(keys, k) }
sort.Strings(keys)
for _, k := range keys { fmt.Printf("%s: %d\n", k, ages[k]) }
注意事项与常见陷阱
使用map时几个关键细节容易出错:
-
nil map不可写也不可读(除len和cap外):未
make的map是nil,直接赋值会panic;len(nilMap)返回0,是安全的 -
map是引用类型,但不是线程安全的:多个goroutine同时读写需加锁(如
sync.RWMutex)或使用sync.Map(适用于读多写少场景) -
结构体作为键需所有字段可比较:
type Key struct{ A int; B string }✅
m := make(map[Key]bool)
但若含切片字段则非法 ❌ - 不要用float64作键:浮点数精度问题可能导致预期外的不相等,建议转为字符串或整数表示










