博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go Map -- 就要学习 Go 语言
阅读量:5843 次
发布时间:2019-06-18

本文共 3641 字,大约阅读时间需要 12 分钟。

前言

Hash表是一种巧妙并且实用的数据结构,是一个无序的key/value对的集合,其中所有的key都是不同的,通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。Map其实是一个Hash表的引用,能够基于键快速检索出数据,键就像索引一样指向与该键关联的值。以后有机会再给大家讲Map底层的东西,教会大家如何使用Map才是这一节的重点,记住一点:Map存储的是无序的键值对集合

创建与初始化

使用make函数

make可以创建切片,也可以用来创建Map。规则是这样的:

m := make(map[keyType]valueType)复制代码

我们来试着创建:

month := make(map[string]int)month["January"] = 1month["February"] = 2month["March"] = 3复制代码

第一行代码,创建了key类型为stringvalue类型为int的空Map month,接着,给month赋值了三个键值对。

使用字面量

上面的代码,可以采用字面量的方式实现:

month := map[string]int{
"January":1,"February":2,"March":3}// 还可以写成这样month := map[string]int{ "January":1, "February":2, "March":3,}复制代码

使用字面量也可以创建空Map,大括号里面不赋值就可以了:

month := map[string]int{}fmt.Println(month)        // 输出:map[]复制代码

有空Map,是不是有nil Map?当然是有为nilMap:

var month map[string]intfmt.Println(month == nil)    // 输出:true复制代码

对于nilmap是不能存取键值对的,否则就会报错panic: assignment to entry in nil map。可以使用提到的make函数,为其初始化:

var month map[string]intmonth = make(map[string]int)month["January"] = 1fmt.Println(month)   // 输出:map[January:1]复制代码

自然能想到,Map的零值就是nilMap就是底层Hash表的引用。 Mapkey可以是内置类型,也可以是结构类型,只要可以使用 == 运算符做比较,都可以作为key切片函数以及包含切片的结构类型,这些类型由于具有引用语义,不能作为key,使用这些类型会造成编译错误:

month := map[[]string]int{}// 编译错误:invalid map key type []string复制代码

对于Mapvalue来说,就没有类型限制,当然也没有任何理由阻止用户使用切片作为Map的值:

m := map[string][]int{}slice := []int{
1,2,3}m["slice"] = slicefmt.Println(m["slice"])// 或者slice := []int{
1,2,3}m := map[string][]int{
"slice":slice}fmt.Println(m["slice"])复制代码

第一段代码,创建了key类型为string,值为slice类型的空Map,接着将切片slice赋值给了名为slicekey。第二段代码是第一段代码的简写版本。

如何使用Map

Map的使用就很简单了,类似于数组,数组是使用索引,Map使用key获取或修改value

m := map[string]int{}m["January"] = 1        // 赋值fmt.Println(m)			// 输出:map[January:1]m["January"] = 10       //修改fmt.Println(m)          // 输出:map[January:10]january := m["January"]   // 获取valuefmt.Println(january)     // 输出:10复制代码

执行修改操作的时候,如果key已经存在,则新值会覆盖旧值,上面代码已经体现出来了,所以key是不允许重复的。 获取一个不存在的keyvalue的时候,会返回值类型对应的零值,这个时候,我们就不知道是存在一个值为零值的键值对还是键值对就根本不存在。好在,Map给我们提供了方法:

february,exists := m["February"]fmt.Println(february,exists)   // 输出:0 false复制代码

获取值的时候多了一个返回值,第一个返回值是value,第二个返回值是boolean类型变量,表示value是否存在。这给我们判断一个key是否存在就提供了很大便利。

delete--删除键值对

不像SliceGo为我们提供了删除键值对的功能--delete函数。 函数原型:

func delete(m map[Type]Type1, key Type)复制代码

第一个参数是Map,第二个参数是key

m := map[string]int{	"January":1,	"February":2,	"March":3,}fmt.Println(m)     // 输出:map[March:3 January:1 February:2]delete(m,"January")fmt.Println(m)     // 输出:map[February:2 March:3]复制代码

删除一个不存在的键值对时,delete函数不会报错,没任何作用。

遍历Map

Map没法使用for循环遍历,跟数组、切片一样,可以使用range遍历。

for key, value := range m {	fmt.Println(key, "=>", value)}复制代码

February => 2March => 3January => 1复制代码

可以使用空白操作符_忽略返回的keyvalue。多次执行代码的时候,你会发现,返回值的顺序有可能是不一样的,也就是说Map的遍历是无序的。

len函数

可以使用len函数返回Map中键值对的数量:

fmt.Println("len(m) =",len(m))复制代码

Map是一种引用类型

Map是对底层数据的引用。编写代码的过程中,会涉及到Map拷贝、函数间传递Map等。跟Slice类似,Map指向的底层数据是不会发生copy的。

m := map[string]int{	"January":1,	"February":2,	"March":3,}month := m    delete(month,"February")fmt.Println(m)fmt.Println(month)复制代码

map[January:1 March:3]map[January:1 March:3]复制代码

上面的代码,将Map m赋值给month,删除了month中的一个键值对,m也发生了改变,说明Map拷贝时,mmonth是共享底层数据的,改变其中一方数据,另一方也会随之改变。类似,在函数间传递Map时,其实传递的是Map的引用,不会涉及底层数据的拷贝,如果在被调用函数中修改了Map,在调用函数中也会感知到Map的变化。 那如果我真想拷贝一个Map怎么办?

month := map[string]int{}m := map[string]int{	"January":1,	"February":2,	"March":3,}for key,value := range m{	month[key] = value}delete(month,"February")fmt.Println(m)fmt.Println(month)复制代码

map[January:1 February:2 March:3]map[January:1 March:3]复制代码

上面的代码,我们使用rangem的键值对循环赋值给了month,然后删除month其中一个键值对,通过打印的结果可以看出,m没有改变。这就实现了真正的拷贝。 关于Map的使用就讲到这,欢迎大家评论交流!

(全文完)

原创文章,若需转载请注明出处!

欢迎扫码关注公众号「Golang来了」或者移步 ,查看更多精彩文章。

关注公众号「Golang来了」,获取最新文章!

你可能感兴趣的文章
python编程(基于twisted的client编程)
查看>>
velocity.properties配置说明
查看>>
获取Map集合中数据的方法
查看>>
王守仁 知行合一
查看>>
ubuntu 12.04 下安装 PyTesser 进行OCR识别 - 从波 - 博客园
查看>>
计算机精品学习资料大放送
查看>>
tomcat通过虚拟路径访问外部静态资源
查看>>
渴望成为架构师的你,或许需要与这些大咖来一场面基
查看>>
什么是NVMe?一篇文章理清它的前生今世
查看>>
饿了么分布式KV架构与实践
查看>>
一张图告诉你,选择企业安全软件真的不难!
查看>>
巴西矿坝决堤事故已致58人死亡 多达300人失踪
查看>>
湖北省首条短途运输航线“荆门—武汉”航线运营
查看>>
「每天一道面试题」AQS是什么?了解其内部同步队列实现结构吗?
查看>>
上海译文公布2019年“新书目录” 名家名译作品结集出版
查看>>
“飞跃四十载 同发展·共繁荣”巡回展在江苏举行
查看>>
掌握6大技巧,让python编程健步如飞!
查看>>
百度亮相NeurIPS 首届Expo:向世界科普了中国自动机器学习框架
查看>>
「备战春招/秋招」美团Java面经总结终结篇(附详解答)
查看>>
外行人都能看懂的SpringCloud,错过了血亏!
查看>>