如何在Golang中使用map存储键值对_创建、访问和遍历Map

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

Go语言中的map是无序的键值对集合,必须先声明再使用(不能像切片那样直接字面量赋值给未声明变量),且键类型必须支持==比较(如stringintbool、指针等,但不能是切片、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"不存在,age0int零值)
  • 安全读取(判断是否存在)
    if age, ok := ages["Bob"]; ok { fmt.Println("Bob is", age) }
    其中okbool,仅当键存在时为true
  • 添加/更新元素ages["Charlie"] = 30(键存在则覆盖,不存在则插入)
  • 删除元素delete(ages, "Alice")(删除不存在的键无副作用)

遍历Map:用for-range,顺序不保证

Go中map遍历顺序是随机的(每次运行可能不同),如需固定顺序,需额外排序键:

  • 基础遍历(键+值)
    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作键:浮点数精度问题可能导致预期外的不相等,建议转为字符串或整数表示