一起学GO之map

什么是map

Map是一种通过key来获取value的一个数据结构,其底层是散列表,在存储时key不能重复,当我们给定 key,就可以迅速找到对应的 value,不过我们要知道Map 是无序的,我们无法决定它的返回顺序。

声明map

1- 因为map是引用类型,可以使用: var mapname map[keyType]valType
2- 通过make内置函数可以创建 map,语法:make(map[keyType] valType)

	languageMap := map[string]int{"Go": 1, "Python": 2}
	fmt.Printf("第一种创建方式: %#v \n", languageMap)

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	fmt.Printf("第二种创建方式: %#v ", animalMap)
	//返回结果
	//第一种创建方式: map[string]int{"Go":1, "Python":2} 
	//第二种创建方式: map[string]int{"cat":2, "dog":1} 

虽然map 可以根据新增的 key-value 动态的伸缩,它不存在固定长度或者最大限制,但是也可以选择标明 map 的初始容量 capacity,语法: make(map[keyType] valType, cap)

map键值的规范

在go中,要能做map的键,必须满足能进行 == 操作,为了方便大家记忆,我们就说go那些不能进行 == 操作:maps, slices 和 functions 不能比较。map的值没有做要求,任何类型都可以

Map的操作

添加元素

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	animalMap["bird"] = 3
	fmt.Printf("animalMap的内容: %#v ", animalMap)
	//返回值
	//animalMap的内容: map[string]int{"bird":3, "cat":2, "dog":1} 

也可以和上面创建map的例子一样,初始化的时候添加元素

删除元素

删除语法: del(mapName, key)

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	animalMap["bird"] = 3
	fmt.Printf("开始--animalMap的内容: %#v \n ", animalMap)
	delete(animalMap, "dog")
	fmt.Printf("删除后的--animalMap的内容: %#v \n", animalMap)
	//返回的结果
	//开始--animalMap的内容: map[string]int{"bird":3, "cat":2, "dog":1} 
    //删除后的--animalMap的内容: map[string]int{"bird":3, "cat":2} 

如果我们删除了一个不存在的key,比如说 “dog1”我们程序是不会抛出异常,另外mao没有提供清除map的方法,如果我们要清除map,可以使用make一个新的 map。

访问元素

1- 可以使用range循环遍历

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	animalMap["bird"] = 3
	for key ,val := range animalMap{
		fmt.Println( key, val)
	}
	//返回结果
	//dog 1
	//cat 2
	//bird 3

第一种方式我们要知道,range不会保证每次返回的元素顺序相同

2- 也可以直接通过key的方式

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	animalMap["bird"] = 3
	fmt.Println(animalMap["bird"])
	//返回结果
	//3

如果用第二种方式我们访问的key不存在,那么我们不需要担心可以和python一样抛出异常,因为如果没有这个key,那么会返回对应类型的零值(int对应的是0)。

获取map的长度

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	animalMap["bird"] = 3
	fmt.Println(len(animalMap))
	// 返回结果
	// 3

map的比较

map 之间不能使用 == 操作符判断,== 只能用来检查 map 是否为 nil

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	animalMap["bird"] = 3
	animalMapNew := animalMap
	if animalMapNew == animalMap{
		fmt.Println("相等")
	}
	//返回结果
	// invalid operation: animalMapNew == animalMap (map can only be compared to nil)

如果我们要判断两个map是否拥有相同的键和值,我们必须写一个循环

func equal(x, y map[string]int) bool {
	if len(x) != len(y) {
		return false
	}
	for k, xv := range x {
		if yv, ok := y[k]; !ok || yv != xv {
			return false
		}
	}
	return true
}

map是引用类型

在一开始的时候我们说过map是引用类型,下面我们通过例子来加深下我们对这句话的印象

	animalMap := make(map[string]int)
	animalMap["dog"] = 1
	animalMap["cat"] = 2
	animalMap["bird"] = 3
	fmt.Println("开始的: ", animalMap)
	animalMapNew := animalMap
	animalMapNew["snake"] = 4
	animalMap["dog"] = 5
	fmt.Println("变更后: ", animalMap)
	//返回结果
	// 开始的:  map[bird:3 cat:2 dog:1]
	// 变更后:  map[bird:3 cat:2 dog:5 snake:4]

上面的例子可以看出:当 map 被赋值为一个新变量的时候,它们指向同一个内部数据结构。因此,改变其中一个变量,就会影响到另一变量。

并发环境中使用的map

Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map。sync.Map 有以下特性:

  • 无须初始化,直接声明即可。
  • sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。
  • 使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。
var scene sync.Map
	//写入数据
	scene.Store("dog", 1)
	scene.Store("cat", 2)
	scene.Store("bird", 3)
	//取值
	fmt.Printf("dog: ")
	fmt.Println(scene.Load("dog"))
	// 删除
	scene.Delete("dog")
	// 遍历
	scene.Range(func(k, v interface{}) bool {
		fmt.Println( k, v)
		return true
	})
	// 返回结果
	//dog: 1 true
	//cat 2
	//bird 3
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木子林_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值