什么是 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. jquery 全选反选 .prop('checked',!$(this).is(':checked'));

    //废话不说直接上代码 $("#").click(function(){ $("#content-div label input[type='checkbox']&quo ...

  2. 波利亚(Polya)罐子模型

    (波利亚(Polya)罐子模型)罐中有a个白球,b个黑球,每次从罐中随机抽取一球,观察其颜色后,连同附加的c个同色球   (波利亚(Polya)罐子模型)罐中有a个白球,b个黑球,每次从罐中随机抽取一 ...

  3. lua 5.3 英文手册 google机器翻译版

    LUA Lua 5.3参考手册作者:Roberto Ierusalimschy,Luiz Henrique de Figueiredo,Waldemar Celes 版权所有©2015-2018 Lu ...

  4. 部署LAMP架构及其应用

    部署企业LAMP架构 (一)首先安装Apache服务,具体请见另一篇关于Apache的博文. (二)安装MySQL数据库,具体请见另一篇关于LNMP的博文. (三)构建PHP运行环境 1.安装PHP ...

  5. Using Request Headers for Metadata Address

    问题描述 我将一个在本地调试正常的service部署到服务器后遇到了添加服务引用失败的问题.在把配置文件中基址使用的localhost替换成服务器的ip地址后问题得到了解决.但我感觉这并不是一个因为粗 ...

  6. 如何调用另一个包中的Application

    在项目中要集成Xabber,将它作为一个Lib, ..... Xabber 原有代码 /** * Base entry point. * * @author alexander.ivanov */ p ...

  7. 3期浅析宽字节注入-----SQL注入

    通过分类的名称,你就可以找到漏洞银行的hack show视频. 吸收这个知识的几个关键的信息. 1.通过视频得到知识源.         [信息来源] 我怎么从不清楚到知道这个信息来源?这个过程没办法 ...

  8. pycharm下运行unittest的问题

    环境: 系统:window7 64 软件:pycharm 版本:2016.3.2 问题描述: 使用unittest类的时候出现问题,问题截图如下 Pycharm 2016.2执行单元测试遇到如下问题: ...

  9. 1016 部分A+B (15 分)

    // 题目不难,感觉变量定义的有点儿多了#include <iostream> #include <cmath> using namespace std; int main() ...

  10. js高级程序设计 笔记 --- 引用类型

    一,变量和作用域 1, js变量可以保存两种类型,基本类型.引用类型和symbol类型,基本类型有5种:undefined.null.boolean.number.string,它们都有以下的特征 基 ...