[Go]新手入门:map的介绍与使用

Posted 凌星An

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Go]新手入门:map的介绍与使用相关的知识,希望对你有一定的参考价值。

介绍

Go语言中的map是一种存放元素对无序集合(数据结构)
元素对:即key-value对;key为键值,value为值;key可以理解为数组的下标,根据key可以快速的找到对应的value值

map在其他语言中也存在对应的数据结构 eg:Python中字典(dict);C++中的map;Java中的HashMap

Go中的map与其他语言存在区别:map作为语言内置类型存在。

使用

创建变量

map是一种引用类型,可以使用make函数或者初始化语句来创建。

eg:

    //声明一个map变量map0 ;key为int类型,value为string类型
    var map0 map[int]string
    //未初始化的map默认值为nil
    //使用len函数可以得出map变量中元素个数,
    //如果是传入未初始的map结果为0
	fmt.Println(map0 == nil, "map0 len", len(map0))
    //true map0 len 0
    
    //使用make函数创建map变量
	map1 := make(map[int]string)
	//往map1中添加元素对
	map1[1] = "one"
	map1[2] = "two"
    //验证结果
	fmt.Println(map1[1], map1[2])
	fmt.Println("map1 len:", len(map1))
    //one two
    //map1 len: 2

    //使用make函数创建map变量,此处指明了初始容量大小为10
    //map可以根据新增的元素对,进行伸缩处理
    //可以不指明初始容量,让其自动扩展
    //但是最有效率的方法是,指明一个大概的范围,
    //防止其扩容(内存分配,重新哈希)造成的效率损失
	map3 := make(map[int]string, 10)
	fmt.Println("map3 len:", len(map3))
    //0     未存入元素
    
    //使用初始化语句创建map变量map2
	map2 := map[int]string1: "one", 2: "two"
	fmt.Println(map2[1], map2[2])

基本操作

增加元素对

往map变量里面增加元素对的方法在上面已经展示过了

mapVar[key]=value
mapVar : map变量
key :新增元素对的键值
value :新增元素对的值

    map1 := make(map[int]string)
	map1[1] = "one"
	map1[2] = "two"
	fmt.Println(map1[1], map1[2])

查找元素对

我们可以使用if语句来判断map变量中是否存在对应的元素对
eg:

	map1 := make(map[int]string)
	map1[1] = "one"
	map1[2] = "two"
	//ok是一个bool变量 
	//为true时,表示map中存在对应元素对,v变量中存储value值
	//为false时,表示map变量中不存在对应元素对
	if v, ok := map1[2]; ok 
		fmt.Println(v)
	 else 
		fmt.Println("map1中不存在键值:2")
	
	if v, ok := map1[3]; ok 
		fmt.Println(v)
	 else 
		fmt.Println("map1中不存在键值:3")
	
	//two
    //map1中不存在键值:3

遍历

使用for循环搭配range关键字可以遍历map
eg:

     map1 := make(map[int]string)
	map1[1] = "one"
	map1[2] = "two"
	// k变量存储键值
	// v变量存储键值对应的值
	for k, v := range map1 
		fmt.Println("key:", k, "value:", v)
	
	//key: 1 value: one
    //key: 2 value: two

    // k变量存储键值
    for k := range map1 
		fmt.Println("key:", k)
	
    //key: 1
    //key: 2

    //使用匿名变量的形式,只接收值,不需要返回键值
	for _, v := range map1 
		fmt.Println("value:", v)
	
	//value: one
    //value: two

注:
map是一种无序的数据结构,也就是说遍历的顺序时未知的,可能每次都不一样;如果希望的到有序的结果;可以使用sort包中对应的函数进行排序

删除元素对

Go中提供内置函数delete可以删除map变量中的单个元素对
usage:

delete(mapVar,key)
mapVar: map变量 key:键值

eg:

map1 := make(map[int]string)
	map1[1] = "one"
	map1[2] = "two"
	for k, v := range map1 
		fmt.Println("key:", k, "value:", v)
	
	//删除键值为1的元素对
	delete(map1, 1)
	for k, v := range map1 
		fmt.Println("key:", k, "value:", v)
	
	//删除不存在的元素对
	delete(map1, 3)
	for k, v := range map1 
		fmt.Println("key:", k, "value:", v)
	
	/*
	key: 1 value: one
    key: 2 value: two
    
    key: 2 value: two
    
    key: 2 value: two
   */

注:
内置函数delete:
func delete(m map[Type]Type1, key Type)
如果 m 为 nil 或没有这样的元素,则 delete 是空操作。

修改元素对

mapVar[key]= NewValue
mapVar :map变量
key:键值
NewValue :新的值
倘若想修改key值,可以先使用delete函数删除元素对,在使用mapVar[key]=value的形式添加元素对

eg:

    map1 := make(map[int]string)
	map1[1] = "one"
	map1[2] = "two"
	for k, v := range map1 
		fmt.Println("key:", k, "value:", v)
	
	map1[1] = "first"
	for k, v := range map1 
		fmt.Println("key:", k, "value:", v)
	
	/*
	key: 1 value: one
    key: 2 value: two
    
    key: 1 value: first
    key: 2 value: two
   */

使用注意事项

在遍历时修改map的值

这种是被允许的;也是安全的不会出现错误

map1 := make(map[string]int)
	map1["one"] = 1
	map1["two"] = 2
	for k, v := range map1 
		map1[k] = v + 1
		fmt.Println("key:", k, "value:", map1[k])
	

key: one value: 2
key: two value: 3

在遍历时新增或者删除 元素对

这种操作也是ok的,是安全的,不会出现任何错误
eg:

map1 := make(map[int]int)
	for i := 0; i < 10; i++ 
		map1[i] = i + 10;
	

	for k, v := range map1 
		if k == 7 
			map1[77] = 77
		
		delete(map1, k)
		fmt.Println("delete <k,v>:<", k, v, ">", "   map1:", map1)
	

delete <k,v>:< 3 13 > map1: map[0:10 1:11 2:12 4:14 5:15 6:16 7:17 8:18 9:19]
delete <k,v>:< 4 14 > map1: map[0:10 1:11 2:12 5:15 6:16 7:17 8:18 9:19]
delete <k,v>:< 6 16 > map1: map[0:10 1:11 2:12 5:15 7:17 8:18 9:19]
delete <k,v>:< 7 17 > map1: map[0:10 1:11 2:12 5:15 8:18 9:19 77:77]
delete <k,v>:< 9 19 > map1: map[0:10 1:11 2:12 5:15 8:18 77:77]
delete <k,v>:< 1 11 > map1: map[0:10 2:12 5:15 8:18 77:77]
delete <k,v>:< 2 12 > map1: map[0:10 5:15 8:18 77:77]
delete <k,v>:< 5 15 > map1: map[0:10 8:18 77:77]
delete <k,v>:< 8 18 > map1: map[0:10 77:77]
delete <k,v>:< 77 77 > map1: map[0:10]
delete <k,v>:< 0 10 > map1: map[]

并发环境

在并发环境下对map进行读写操作是不安全的,存在数据竞争。
在Go 1.9后,引入sync.Map 在并发下是安全的

	const size = 100
	map1 := make(map[int]int)
	go func() 
		for i := 0; i < size; i++ 
			map1[i] = i
		
	()
	go func() 
		for i := 0; i < size; i++ 
			fmt.Println(map1[i])
		
	()

go run -race main.go
==================
WARNING: DATA RACE

关于nil map

仅仅声明map变量,它的默认值是nil。
对于值为nil的map变量,go圣经中有一句说明:
Most operations on maps, including lookup, delete, len, and range loops, are safe to perform on a nil map reference, since it behaves like an emtpy map. But storing to a nil map cause a panic.

如果往nil map存储值得时候将会导致程序崩溃

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

觉得不错,来个赞呗

以上是关于[Go]新手入门:map的介绍与使用的主要内容,如果未能解决你的问题,请参考以下文章

从入门到掉坑:Go 内存池/对象池技术介绍

Go入门教程2内置基础类型(Boolean数值字符串错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值

Golang 入门总结:Go Module, for range, 切片, map, struct 等使用和实现

Golang 入门总结:Go Module, for range, 切片, map, struct 等使用和实现

Go 语言入门很简单 -- 8. Go Maps #私藏项目实操分享#

Go语言入门Map&函数