• 【愚公系列】2022年07月 Go教学课程 022-Go容器之字典



    一、Go容器之字典

    1.什么是字典

    Go 中字典也叫做 map , map 是一种无序的键值对的集合,使用散列表(hash)实现。

    2.字典的定义

    var 变量名 [keyType]valueType
    
    • 1
    • keyType 表示键类型。
    • valueType 表示键对应的值类型。

    2.1 第一种使用方式make

    package main
    
    import "fmt"
    
    func main() {
    	// 定义一个键类型为字符串,值类型为整型的 map
    	m := make(map[int]string)
    
    	// 向 map 中添加一个键为 “1”,值为 愚公1号 的映射关系
    	key := 1
    	m[key] = "愚公1号"
    
    	// 输出 map 中键为 “1” 对应的值
    	fmt.Println(m[key])
    
    	// 声明一个 ok 变量,用来接收对应键是否存在于 map 中
    	value, ok := m[key]
    
    	// 如果值不存在,则输出值
    	if ok {
    		fmt.Println(value)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    2.2 第二种使用方式{}

    package main
    
    import "fmt"
    
    func main() {
    	// 定义一个键类型为字符串,值类型为整型的 map
    	m := map[int](string){
    		1: "愚公1号",
    		2: "愚公2号",
    		3: "愚公3号",
    	}
    
    	// 输出 map 中键为 “1” 对应的值
    	fmt.Println(m[1])
    
    	// 声明一个 ok 变量,用来接收对应键是否存在于 map 中
    	value, ok := m[2]
    
    	// 如果值不存在,则输出值
    	if ok {
    		fmt.Println(value)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述
    上面的这段代码并没有使用 make(), 而是通过大括号的方式来初始化字典 map, 有点像 JSON 格式一样,冒号左边的是键(key) , 右边的是值(value) ,键值对之间使用逗号分隔。

    二、字典的遍历

    package main
    
    import "fmt"
    
    func main() {
    	m := map[int](string){
    		1: "愚公1号",
    		2: "愚公2号",
    		3: "愚公3号",
    	}
    
    	// 通过 for range 遍历, 获取 key, value 值并打印
    	for key, value := range m {
    		fmt.Printf("key: %d, value: %s\n", key, value)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述
    注意: 字典 map 是一种无序的数据结构,输出是不按顺序是随机的。

    三、字典的键值对删除

    delete(map,)
    
    • 1
    • map 表示要删除的目标 map 对象。
    • 键表示要删除的 map 中 key 键。

    相关案例:

    package main
    
    import "fmt"
    
    func main() {
    	m := map[int](string){
    		1: "愚公1号",
    		2: "愚公2号",
    		3: "愚公3号",
    	}
    
    	// 删除 map 中键为 1 的键值对
    	delete(m, 1)
    
    	// 通过 for range 遍历, 获取 key, value 值并打印
    	for key, value := range m {
    		fmt.Println(key, value)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    四、异步sync.Map

    1.map的并发问题

    Go的字典只读是线程安全的,同时读写是线程不安全的。

    package main
    
    func main()  {
    	// 初始化一个键为整型,值也为整型的 map
    	m := make(map[int]int)
    
    	// 开启一段并发代码
    	go func() {
    		// 无限循环往 map 里写值
    		for {
    			m[1] = 1
    		}
    	}()
    
    	// 开启一段并发代码
    	go func() {
    		// 无限循环读取 map 数据
    		for {
    			_ = m[1]
    		}
    	}()
    
    	// 死循环,让上面的并发代码在后台执行
    	for {
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述
    因为并发的对 map 进行读写。两个并发函数不断的对 map 进行读写发生了竞态问题。map 内部会对这种并发操作进行检查并提前发现。

    2.sync.Map的使用

    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    func main() {
    	var m sync.Map
    
    	// 添加一些键值对到 map 中
    	m.Store(1, "愚公1号")
    	m.Store(2, "愚公2号")
    	m.Store(3, "愚公3号")
    
    	// 从 sync.Map 中获取键为 2 的值
    	fmt.Println(m.Load(2))
    
    	// 删除键值对
    	m.Delete(1)
    
    	// 遍历 sync.Map 中的键值对
    	m.Range(func(key, value interface{}) bool {
    		fmt.Printf("key: %d, value: %s\n", key, value)
    		return true
    	})
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

  • 相关阅读:
    树和图的基础知识(洛谷)
    springcloud: stream整合rocketmq
    柒微自动发卡系统源码
    记录一下自行安装RabbitMQ的步骤
    STM32 NVIC中断优先级管理通过结构图快速理解
    http https http2 http3
    RISV-V架构的寄存器介绍
    初学者设计PCB,如何检查光绘文件的断头线
    IO多路转接之select和poll
    自动化办公02 用openpyxl库操作excel.xlsx文件(新版本)
  • 原文地址:https://blog.csdn.net/aa2528877987/article/details/126079307