什么是 map?

Map 是 Go 中的内置类型,它将键与值绑定到一起。可以通过键获取相应的值。

如何创建 map?

可以通过将键和值的类型传递给内置函数 make 来创建一个 map。语法为:make(map[KeyType]ValueType)。(译者注:map 的类型表示为 map[KeyType]ValueType)例如:

personSalary := make(map[string]int)

上面的代码创建了一个名为 personSalary 的 map。其中键的类型为 string,值的类型为 int。

map 的 0 值为 nil。试图给一个 nil map 添加元素给会导致运行时错误。因此 map 必须通过 make 来初始化(译者注:也可以使用速记声明来创建 map,见下文)。

package main

import (
"fmt"
) func main() {
var personSalary map[string]int
if personSalary == nil {
fmt.Println("map is nil. Going to make one.")
personSalary = make(map[string]int)
}
}

上面的程序中,personSalary 为 nil,因此使用 make 初始化它。程序的输出为:map is nil. Going to make one.

向 map 中插入元素

插入元素给 map 的语法与数组相似。下面的代码插入一些新的元素给 map personSalary

package main

import (
"fmt"
) func main() {
personSalary := make(map[string]int)
personSalary["steve"] =
personSalary["jamie"] =
personSalary["mike"] =
fmt.Println("personSalary map contents:", personSalary)
}

上面的程序输出:personSalary map contents: map[steve:12000 jamie:15000 mike:9000]

也可以在声明时初始化一个数组:

package main

import (
"fmt"
) func main() {
personSalary := map[string]int {
"steve": ,
"jamie": ,
}
personSalary["mike"] =
fmt.Println("personSalary map contents:", personSalary)
}

上面的程序在声明 personSalary 的同时向其中插入了两个元素。接着插入了一个以 "mike" 为键的元素。程序的输出为:

personSalary map contents: map[steve: jamie: mike:] 

string 并不是可以作为键的唯一类型,其他所有可以比较的类型,比如,布尔类型,整型,浮点型,复数类型都可以作为键。如果你想了解更多关于可比较类型的话,请参阅:http://golang.org/ref/spec#Comparison_operators

访问 map 中的元素

现在我们已经添加了一些元素给 map,现在让我们学习如何从 map 中提取它们。根据键获取值的语法为:map[key],例如:

package main

import (
"fmt"
) func main() {
personSalary := map[string]int{
"steve": ,
"jamie": ,
}
personSalary["mike"] =
employee := "jamie"
fmt.Println("Salary of", employee, "is", personSalary[employee])
}

上面的程序非常简单。员工 jamie 的工资被取出并打印。程序的输出为:Salary of jamie is 15000

如果一个键不存在会发生什么?map 会返回值类型的 0 值。比如如果访问了 personSalary 中的不存在的键,那么将返回 int 的 0 值,也就是 0。

package main

import (
"fmt"
) func main() {
personSalary := map[string]int{
"steve": ,
"jamie": ,
}
personSalary["mike"] =
employee := "jamie"
fmt.Println("Salary of", employee, "is", personSalary[employee])
fmt.Println("Salary of joe is", personSalary["joe"])
}

上面的程序输出为:

Salary of jamie is
Salary of joe is

上面的程序返回 joe 的工资为 0。我们没有得到任何运行时错误说明键 joe 在 personSalary 中不存在。

我们如何检测一个键是否存在于一个 map 中呢?可以使用下面的语法:

value, ok := map[key]  

上面的语法可以检测一个特定的键是否存在于 map 中。如果 ok 是 true,则键存在,value 被赋值为对应的值。如果 ok为 false,则表示键不存在。

package main

import (
"fmt"
) func main() {
personSalary := map[string]int{
"steve": ,
"jamie": ,
}
personSalary["mike"] =
newEmp := "joe"
value, ok := personSalary[newEmp]
if ok == true {
fmt.Println("Salary of", newEmp, "is", value)
} else {
fmt.Println(newEmp,"not found")
} }

在上面的程序中,第 15 行,ok 应该为 false 因为 joe 不存在。因此程序的输出为:

joe not found  

range for 可用于遍历 map 中所有的元素(译者注:这里 range 操作符会返回 map 的键和值)。

package main

import (
"fmt"
) func main() {
personSalary := map[string]int{
"steve": ,
"jamie": ,
}
personSalary["mike"] =
fmt.Println("All items of a map")
for key, value := range personSalary {
fmt.Printf("personSalary[%s] = %d\n", key, value)
} }

上面的程序输出如下:

All items of a map
personSalary[mike] =
personSalary[steve] =
personSalary[jamie] =

值得注意的是,因为 map 是无序的,因此对于程序的每次执行,不能保证使用 range for 遍历 map 的顺序总是一致的。

删除元素

delete(map, key) 用于删除 map 中的 key。delete 函数没有返回值。

package main

import (
"fmt"
) func main() {
personSalary := map[string]int{
"steve": ,
"jamie": ,
}
personSalary["mike"] =
fmt.Println("map before deletion", personSalary)
delete(personSalary, "steve")
fmt.Println("map after deletion", personSalary) }

上面的程序删除以 steve 为键的元素。程序输出为:

map before deletion map[steve: jamie: mike:]
map after deletion map[mike: jamie:]

map 的大小

用内置函数 len 获取 map 的大小:

package main

import (
"fmt"
) func main() {
personSalary := map[string]int{
"steve": ,
"jamie": ,
}
personSalary["mike"] =
fmt.Println("length is", len(personSalary)) }

上面程序中,len(personSalary) 获取 personSalary 的大小。上面的程序输出:length is 3

map 是引用类型

切片一样,map 是引用类型。当一个 map 赋值给一个新的变量,它们都指向同一个内部数据结构。因此改变其中一个也会反映到另一个:

package main

import (
"fmt"
) func main() {
personSalary := map[string]int{
"steve": ,
"jamie": ,
}
personSalary["mike"] =
fmt.Println("Original person salary", personSalary)
newPersonSalary := personSalary
newPersonSalary["mike"] =
fmt.Println("Person salary changed", personSalary)
}

上面的程序中,第 14 行,personSalary 赋值给 newPersonSalary。下一行,将 newPersonSalary 中 mike 的工资改为 18000。那么在 personSalary 中 mike 的工资也将变为 18000。程序的输出如下:

Original person salary map[steve: jamie: mike:]
Person salary changed map[jamie: mike: steve:]

将 map 作为参数传递给函数也是一样的。在函数中对 map 的任何修改都会影响在调用函数中看到。

Golang教程:Map的更多相关文章

  1. Golang基础教程——map使用篇

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第7篇文章,我们来聊聊golang当中map的用法. map这个数据结构我们经常使用,存储的是key-value的键 ...

  2. Golang中map的三种声明方式和简单实现增删改查

    package main import ( "fmt" ) func main() { test3 := map[string]string{ "one": & ...

  3. 总结golang之map

    总结golang之map 2017年04月13日 23:35:53 趁年轻造起来 阅读数:18637 标签: golangmapgo 更多 个人分类: golang   版权声明:本文为博主原创文章, ...

  4. golang 中 map 转 struct

    golang 中 map 转 struct package main import ( "fmt" "github.com/goinggo/mapstructure&qu ...

  5. golang之map的使用声明

    1.map的基本介绍 map是key-value数据结构,又称为字段或者关联数组.类似其它编程语言的集合,在编程中是经常使用到的 2.map的声明 1)基本语法 var map 变量名 map[key ...

  6. Golang:sync.Map

    由于map在gorountine 上不是安全的,所以在大量并发读写的时候,会出现错误. 在1.9版的时候golang推出了sync.Map. sync.Map 通过阅读源码我们发现sync.Map是通 ...

  7. Golang教程:变量

    声明单一变量 声明一个变量的语法为:var name type,例如 package main import "fmt" func main() { var age int // ...

  8. Golang教程:goroutine信道

    在上一篇教程中,我们讨论了如何使用协程实现并发.在这篇教程中,我们将讨论信道以及如何使用信道实现协程间通信. 什么是信道 信道(Channel)可以被认为是协程之间通信的管道.与水流从管道的一端流向另 ...

  9. 手把手golang教程【二】——数组与切片

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第五篇,这一篇我们将会了解golang中的数组和切片的使用. 数组与切片 golang当中数组和C++中的定义类似, ...

随机推荐

  1. C# 二维码生成——QRCode

    C#二维码生成,这里使用开源的ThoughtWorks.QRCode.dll库. 步骤: 1.下载ThoughtWorks.QRCode.dll库文件,并引用到项目中. 2.创建QRCodeHandl ...

  2. C# Winform Label内容根据其宽度自动调整字体大小

    C# Winform Label内容根据其宽度自动调整字体大小 项目,有个要求,Label中显示的内容,能够根据其宽度自动调整字体的大小进行显示,刚刚开始的时候,总是想着通过不同的方法来直接测量内容的 ...

  3. webapi之权限验证

    webapi之权限验证 一.概念: 二.demo: 1.登录时生成token: FormsAuthenticationTicket token = , account, DateTime.Now, D ...

  4. javascript小数求整

    Math.ceil(arg) 返回一个比参数arg大的整数 Math.floor(arg) 返回一个比参数arg小的整数 Math.round(arg) 返回一个参数arg四舍五入的后的整数 pars ...

  5. Android应用开发以及设计思想深度剖析

    Android应用开发以及设计思想深度剖析(1) 21cnbao.blog.51cto.com/109393/956049

  6. 9、select 语句

    基础语句 select * from tb1; select * from tb1 limit 3; select name,age from tb1; select name,age from tb ...

  7. mysqli扩展库应用---程序范例

    通过mysqli扩展库对用户表user1进行增删改查操作,用户表user1结构如下: 1,建立数据库操作类库mysqliTool.class.php,代码如下: <?php class mysq ...

  8. inception_web

    1) wget --no-check-certificate https://bootstrap.pypa.io/ez_setup.py 2) python ez_setup.py --insecur ...

  9. jquer 使用原生DOM对象

    js中使document.getElementById("ID"); Jquery中可以使用$("#id") 或者$("#id").get( ...

  10. Hibernate 使用注释书写配置文件

    Hibernate 使用注释 Hibernate使用注释有个好处就是我们不需要建立.hbm.xml文件,直接在实体类中添加注解就可以完成往数据库中进行数据操作 配置文件:hibernate.cfg.x ...