ZhouChuang's Blog ZhouChuang's Blog
首页
  • 常用命令
  • 日常总结
  • Prometheus
  • 基础
  • 常用库
专题
  • 「编码」
更多
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Zhou Chuang

为学日益 为道日损
首页
  • 常用命令
  • 日常总结
  • Prometheus
  • 基础
  • 常用库
专题
  • 「编码」
更多
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Go语言基础

    • 安装Go环境
    • 变量、常量
    • 基本数据类型
    • 操作符和流程控制
    • 数组
    • 切片 Slice
    • map
      • map 基本操作
      • 小结:
    • 函数
    • 指针
    • 结构体
    • 接口
  • 常用库

  • 数据库相关内容

  • 技巧

  • golang
  • Go语言基础
ZhouChuang
2024-09-14
目录

map

map是Go语言提供的一种抽象数据类型,它表示一组无序的键值对。

map类型不支持“零值可用”,未显式赋初值的map类型变量的零值为nil。对处于零值状态的map变量进行操作将会导致运行时panic:

var m map[string]int // m = nil
m["key"] = 1         // panic: assignment to entry in nil map
1
2

我们必须对map类型变量进行显式初始化后才能使用它。和切片一样,创建map类型变量有两种方式:一种是使用复合字面值,另一种是使用make这个预声明的内置函数。

  1. 使用复合字面值

    userInfo := map[string]string{
    		"username": "Jack",
    		"password": "123456",
    	}
    
    1
    2
    3
    4
  2. 使用 make()

    scoreMap := make(map[string]int, 8)
    
    1

和切片一样,map也是引用类型,将map类型变量作为函数参数传入不会有很大的性能损耗,并且在函数内部对map变量的修改在函数外部也是可见的

func foo(m map[string]int) {
    m["key1"] = 11
    m["key2"] = 12
}

func main() {
    m := map[string]int{
        "key1": 1,
        "key2": 2,
    }

    fmt.Println(m) // map[key1:1 key2:2]
    foo(m)
    fmt.Println(m) // map[key1:11 key2:12]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# map 基本操作

  1. 插入数据

    面对一个非nil的map类型变量,我们可以向其中插入符合map类型定义的任意键值对。Go运行时会负责map内部的内存管理,因此除非是系统内存耗尽,我们不用担心向map中插入数据的数量。

    m := make(map[K]V)
    m[k1] = v1
    m[k2] = v2
    m[k3] = v3
    
    1
    2
    3
    4

    如果key已经存在于map中,则该操作会用新值覆盖旧值。

  2. 获取数据个数

    和切片一样,map也可以通过内置函数len获取当前已经存储的数据个数

  3. 查询和数据读取

    map类型更多用在查找和数据读取场合。所谓查找就是判断某个key是否存在于某个map中。我们可以使用“comma ok”惯用法来进行查找:

    value, ok := map[key]
    
    1

    例子:

    func main() {
    	scoreMap := make(map[string]int)
    	scoreMap["张三"] = 90
    	scoreMap["李四"] = 100
    	// 如果key存在ok为true,v为对应的值;不存在ok为false,v为值类型的零值
    	v, ok := scoreMap["张三"]
    	if ok {
    		fmt.Println(v)
    	} else {
    		fmt.Println("查无此人")
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  4. 删除元素

    使用delete()内建函数从map中删除一组键值对,delete()函数的格式如下:

    delete(map, key)
    
    1
    • map:表示要删除键值对的map
    • key:表示要删除的键值对的键
  5. 遍历数据

    我们可以像对待切片那样通过for range语句对map中的数据进行遍历

    for k,v := range scoreMap{
    		fmt.Println(k, v)
    }
    
    1
    2
    3

    Go运行时在初始化map迭代器时对起始位置做了随机处理。因此千万不要依赖遍历map所得到的元素次序。

    如果你需要一个稳定的遍历次序,那么一个比较通用的做法是使用另一种数据结构来按需要的次序保存key,比如切片:

    func main() {
    	rand.Seed(time.Now().UnixNano()) //初始化随机数种子
    
    	var scoreMap = make(map[string]int, 200)
    
    	for i := 0; i < 100; i++ {
    		key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
    		value := rand.Intn(100)          //生成0~99的随机整数
    		scoreMap[key] = value
    	}
    	//取出map中的所有key存入切片keys
    	var keys = make([]string, 0, 200)
    	for key := range scoreMap {
    		keys = append(keys, key)
    	}
    	//对切片进行排序
    	sort.Strings(keys)
    	//按照排序后的key遍历map
    	for _, key := range keys {
    		fmt.Println(key, scoreMap[key])
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    # 小结:

    和切片一样,map是Go语言提供的重要数据类型,也是日常编码中最常使用的类型之一。

    我们在日常使用map的场合要把握住下面几个要点:

    • 不要依赖map的元素遍历顺序;
    • map不是线程安全的,不支持并发写;
    • 不要尝试获取map中元素(value)的地址;
    • 尽量使用cap参数创建map,以提升map平均访问性能,减少频繁扩容带来的不必要损耗。
#go 基础
上次更新: 2025/05/06, 13:52:56
切片 Slice
函数

← 切片 Slice 函数→

最近更新
01
find 命令介绍
05-06
02
交换分区的配置
04-09
03
top 命令介绍
04-08
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Zhou Chuang 版权所有| 鲁ICP备2021031629号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式