教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 golang 映射 map 简介

golang 映射 map 简介

发布时间:2022-02-19   编辑:jiaochengji.com
教程集为您提供golang 映射 map 简介等资源,欢迎您收藏本站,我们将为您提供最新的golang 映射 map 简介资源

映射是一种数据结构,用于存储一系列无序的键值对,它基于键来存储值。映射的特点是能够基于键快速检索数据。键就像是数组的索引一样,指向与键关联的值。
与 C 、Java 等编程语言不同,在 Golang 中使用映射不需要引入任何库。因此 Golang 的映射使用起来更加方便。我们可以通过下图简要的理解一下映射中键值对的关系:

 

图中的每个键值对表示一种颜色的字符串名称及其对应的十六进制值,其中名称为键,十六进制数为值。

<h3>映射的实现</h3>

映射是一个数据集合,所以可以是使用类似处理数组和切片的方式来迭代映射中的元素。但映射是无序集合,所以即使以同样的顺序保存键值对,迭代映射时,元素的顺序可能会不一样。无序的原因是映射的实现使用了哈希表。
Golang 中的映射在底层是用哈希表实现的,在 /usr/local/go/src/runtime/hashmap.go 中可以查看它的实现细节。而 C 中的映射则是使用红黑树实现的。

 

<h3>创建和初始化映射</h3>

Golang 中有很多种方法可以创建并初始化映射,可以使用内置的 make 函数,也可以使用映射字面量。

使用 make 函数声明映射

<pre class="has"><code class="language-Go">// 创建一个映射,键的类型是 string,值的类型是 int myMap := make(map[string]int) </code></pre>

使用字面量声明映射

<pre class="has"><code class="language-Go">// 创建一个映射,键和值的类型都是 string // 使用两个键值对初始化映射 myMap := map[string]string{"Red": "#da1337", "Orange": "#e95a22"} </code></pre>

创建映射时,更常用的方法是使用映射字面量。映射的初始长度会根据初始化时指定的键值对的数量来确定。

映射的键可以是任何值
这个值的类型可以是内置的类型,也可以是结构类型,只要这个值可以使用 == 运算符做比较。切片、函数以及包含切片的结构类型,这些类型由于具有引用语义,不能作为映射的键,使用这些类型会造成编译错误:

<pre class="has"><code class="language-Go">// 使用映射字面量声明空映射 // 创建一个映射,使用字符串切片作为映射的键 myMap := map[[]string]int{} </code></pre>

如果你使用的 IDE 支持语法检查,就会提示这段代码有语法错误:

 

如果直接编译上面的代码,会得到一个编译时错误:
invalid map key type []string

虽然切片不能作为映射的键,但是却可以作为映射的值,这个在使用一个映射键对应一组数据时,会非常有用:

<pre class="has"><code class="language-Go">// 声明一个存储字符串切片的映射 // 创建一个映射,使用字符串切片作为值 myMap := map[int][]string{} </code></pre> <h3> </h3> <h3>元素赋值</h3>

通过指定适当类型的键并给这个键赋一个值就完成了映射的键值对赋值:

<pre class="has"><code class="language-Go">// 创建一个空映射,用来存储颜色以及颜色对应的十六进制代码 myColors := map[string]string{} // 将 Red 的代码加入到映射 myColors["Red"] = "#da1337" </code></pre>

与切片类似,可以通过声明一个未初始化的映射来创建一个值为 nil 的映射(一般称为 nil 映射),nil 映射不能用于存储键值对:

<pre class="has"><code class="language-Go">// 通过声明映射创建一个 nil 映射 var myColors map[string]string // 将 Red 的代码加入到映射 myColors["Red"] = "#da1337" </code></pre>

运行这段代码会产生一个运行时错误:
panic: assignment to entry in nil map

<h3> </h3> <h3>查找与遍历</h3>

测试键值是否存在
查找映射里是否存在某个键是映射的一个基本操作。这个操作往往需要用户写一些逻辑代码,根据逻辑代码确定是否完成了某个操作或者映射里是否缓存了某些数据。查找操作也可以用来比较两个映射,确定哪些键值对互相匹配,哪些键值对不匹配。
有两种方法可以检查键值对是否存在,第一种方式是获取键值对中的值以及一个表示这个键是否存在的布尔类型标志:

<pre class="has"><code class="language-Go">// 获取键 Blue 对应的值 value, exists := myColors["Blue"] // 这个键存在吗? if exists { fmt.Println(value) } </code></pre>

另一中方式是,只返回键对应的值,然后通过判断这个值是不是零值来确定键是否存在:

<pre class="has"><code class="language-Go">// 获取键 Blue 对应的值 value := myColors["Blue"] // 这个键存在吗? if value != "" { fmt.Println(value) } </code></pre>

显然,这种方式只能用在映射存储的值都是非零值的情况下。
注意:在 Golang 中,通过键来索引映射时,即便这个键不存在也总会返回一个值。在这种情况下,返回的是该值对应的类型的零值。

遍历映射
和遍历数组、切片一样,使用关键字 range 可以遍历映射中的所有值。但对映射来说,range 返回的不是索引和值,而是键值对:

<pre class="has"><code class="language-Go">// 创建一个映射,存储颜色以及颜色对应的十六进制代码 myColors := map[string]string{ "AliceBlue":"#f0f8ff", "Coral":"#ff7F50", "DarkGray":"#a9a9a9", "ForestGreen": "#228b22", } // 显示映射里的所有颜色 for key, value := range myColors { fmt.Printf("Key: %s Value: %s\n", key, value) } </code></pre>

执行上面的代码,输出如下:

<pre class="has"><code class="language-bash">Key: AliceBlue Value: #f0f8ff Key: Coral Value: #ff7F50 Key: DarkGray Value: #a9a9a9 Key: ForestGreen Value: #228b22 </code></pre> <h3> </h3> <h3>删除映射中的元素</h3>

Golang 提供了一个内置的函数 delete() 用于删除集合中的元素,下面是一个简单的例子:
delete(myMap, "hello")
上面的代码将从 myMap 中删除键为 hello 的键值对。如果 hello 这个键不存在,那么这个调用将什么都不会发生,也不会有什么副作用。但是如果传入的映射的变量的值为 nil,该调用将导致程序抛出异常(panic)。
还以前面定义的 myColors 映射为例,我们用 delete() 函数删除其中的 Coral:

<pre class="has"><code class="language-Go">// 创建一个映射,存储颜色以及颜色对应的十六进制代码 myColors := map[string]string{ "AliceBlue":"#f0f8ff", "Coral":"#ff7F50", "DarkGray":"#a9a9a9", "ForestGreen": "#228b22", } // 删除键为Coral的键值对 delete(myColors, "Coral") // 显示映射里的所有颜色 for key, value := range myColors { fmt.Printf("Key: %s Value: %s\n", key, value) } </code></pre>

执行上面的代码,发现输出的结果中已经没有 Coral 了:

<pre class="has"><code class="language-bash">Key: DarkGray Value: #a9a9a9 Key: ForestGreen Value: #228b22 Key: AliceBlue Value: #f0f8ff </code></pre> <h3> </h3> <h3>在函数间传递映射</h3>

在函数间传递映射并不会制造出该映射的一个副本。实际上,当传递映射给一个函数,并对这个映射做了修改时,所有对这个映射的引用都会察觉到这个修改:

<pre class="has"><code class="language-Go">package main import "fmt" func main() { // 创建一个映射,存储颜色以及颜色对应的十六进制代码 myColors := map[string]string{ "AliceBlue":"#f0f8ff", "Coral":"#ff7F50", "DarkGray":"#a9a9a9", "ForestGreen": "#228b22", } // 显示映射里的所有颜色 for key, value := range myColors { fmt.Printf("Key: %s Value: %s\n", key, value) } fmt.Println() // 调用函数来移除指定的键 removeColor(myColors, "Coral") // 显示映射里的所有颜色 for key, value := range myColors { fmt.Printf("Key: %s Value: %s\n", key, value) } } // removeColor 将指定映射里的键删除 func removeColor(colors map[string]string, key string) { delete(colors, key) } </code></pre>

运行上面的程序,输出如下结果:

<pre class="has"><code class="language-bash">Key: Coral Value: #ff7F50 Key: DarkGray Value: #a9a9a9 Key: ForestGreen Value: #228b22 Key: AliceBlue Value: #f0f8ff Key: AliceBlue Value: #f0f8ff Key: DarkGray Value: #a9a9a9 Key: ForestGreen Value: #228b22 </code></pre>

可以看到,在调用了 removeColor 函数后,main 函数中引用的映射中也不再有 Coral 颜色了。这个特性和切片类似,保证可以用很小的成本来复制映射。

 

<h3>总结</h3>

映射是 Golang 中内置的保存键值对类型数据的类型。从本文的示例中可以看出,Golang 映射实现的简单易用,并且在函数间传递时的性能很好、开销很低。

 

 

到此这篇关于“golang 映射 map 简介”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
golang 映射 map 简介
Golang 映射 声明使用原理及方法
golang map多层嵌套使用及遍历方法汇总
golang 并发访问map遇到的问题
golang map 初始化 和 使用
go-反射机制
golang key map 所有_谨慎使用golang中的map
golang map key 正则表达_Golang中的Map
vim利用map映射执行脚本
Golang map 并发读写问题源码分析

[关闭]
~ ~