Go语言学习之映射(map)的用法详解

目录
  • 1. 什么是 map
  • 2. 创建 map
  • 3. 访问 map
  • 4. nil map和空map
  • 5. map中元素的返回值
  • 6. len()和delete()
  • 7. 测试map中元素是否存在
  • 8. 迭代遍历 map
  • 9. 获取map中所有的key
  • 10. 传递map给函数

1. 什么是 map

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值

Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的

Map 是引用类型,必须初始化才能使用。其中,key的类型除了切片等引用类型,其他类型都可以;而value则可使用所有类型的值

2. 创建 map

可以通过make()创建map,它会先创建好底层数据结构,然后再创建map,并让map指向底层数据结构

my_map := make(map[string]int)

[string]表示map的key的数据类型

int表示key对应的值

直接通过大括号创建并初始化赋值:

// 空map
my_map := map[string]string{}

// 初始化赋值
my_map := map[string]string{"Red": "#da1337","Orange": '#e95a22"}

// 格式化赋值
my_map := map[string]int{
"Java":11,
"Perl":8,
"Python":13, // 注意结尾的逗号不能少
}

注意:

其中map的key可以是任意内置的数据类型(如int),或者其它可以通过 == 进行等值比较的数据类型,如interface和指针可以,slice、数组、map、struct类型都不能作为key ,并且key必须唯一。

但value基本可以是任意类型,例如嵌套一个slice到map中:

my_map := map[string][]int{}

3. 访问 map

访问map中的元素时,指定它的key即可,注意string类型的key必须加上引号:

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 10,
        "2": 20,
        "3": 30,
        "4": 40,
    }

    //访问
    fmt.Println(my_map["1"])
    fmt.Println(my_map)

    fmt.Println("")

    //赋值已有的key & value
    my_map["2"] = 50
    fmt.Println(my_map["2"])
    fmt.Println(my_map)

    fmt.Println("")

    //赋值新的key&value
    my_map["5"] = 66
    fmt.Println(my_map["5"])
    fmt.Println(my_map)
}

输出结果

10
map[1:10 2:20 3:30 4:40]
50
map[1:10 2:50 3:30 4:40]
66
map[1:10 2:50 3:30 4:40 5:66]

4. nil map和空map

空map是不做任何赋值的map:

// 空map
package main

import "fmt"

func main() {
    my_map := map[string]string{}

    fmt.Println(my_map)
}

输出结果

map[]

nil map,它将不会做任何初始化,不会指向任何数据结构:

// nil map
var my_map map[string]string

nil map和empty map的关系,就像nil slice和empty slice一样,两者都是空对象,未存储任何数据,但前者不指向底层数据结构,后者指向底层数据结构,只不过指向的底层对象是空对象。

使用println输出看下即可知道:

package main

func main() {
    var nil_map map[string]string
    println(nil_map)

    emp_map := map[string]string{}
    println(emp_map)
}

输出结果:

0x0
0xc04204de38

所以,map类型实际上就是一个指针。

5. map中元素的返回值

当访问map中某个元素的时候,有两种返回值的格式:

value := my_map["key"]
value,exists := my_map["key"]

第一种很好理解,就是检索map中key对应的value值。如果key不存在,则value返回值对应数据类型的0。例如int为数值0,布尔为false,字符串为空""。

第二种不仅返回key对应的值,还根据key是否存在返回一个布尔值赋值给exists变量。所以,当key存在时,value为对应的值,exists为true;当key不存在,value为0(同样是各数据类型所代表的0),exists为false。

看下例子:

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 10,
        "2": 20,
        "3": 30,
        "4": 40,
    }
    a := my_map["1"]
    b, exists1 := my_map["2"]
    c, exists2 := my_map["5"]
    fmt.Println(a)
    fmt.Println(b, exists1)
    fmt.Println(c, exists2)
}

上面将输出如下结果:

10
20 true
0 false

在Go中设置类似于这种多个返回值的情况很多,即便是自己编写函数也会经常设置它的exists属性。

6. len()和delete()

len()函数用于获取map中元素的个数,即有多个少key。delete()用于删除map中的某个key。

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 10,
        "2": 20,
        "3": 30,
        "4": 40,
    }

    fmt.Printf("删除前长度为%d\n", len(my_map))
    delete(my_map, "1")
    fmt.Printf("删除后长度为%d", len(my_map))
}

输出结果如下

删除前长度为4
删除后长度为3

7. 测试map中元素是否存在

两种方式可以测试map中是否存在某个key:

① 根据map元素的第二个返回值来判断

② 根据返回的value是否为0(不同数据类型的0不同)来判断

方式一:直接访问map中的该元素,将其赋值给两个变量,第二个变量就是元素是否存在的修饰变量。

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 10,
        "2": 20,
        "3": 30,
        "4": 40,
    }

//方法1
/* value, exists := my_map["1"]
    if exists {
        fmt.Println("存在", value)
    }
 */

    //方法2
    if value, exists := my_map["1"]; exists {
        fmt.Printf("值存在, value=%d", value)
    }
}

输出结果如下

值存在, value=10

方式二:根据map元素返回的value判断。因为该map中的value部分是int类型,所以它的0是数值的0。

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 10,
        "2": 20,
        "3": 30,
        "4": 40,
    }

    value := my_map["5"]
    if value == 0 {
        fmt.Println("不存在")
    }
}

输出结果如下

不存在

如果map的value数据类型是string,则判断是否为空:

package main

import "fmt"

func main() {
    my_map := map[string]string{
        "1": "book",
        "2": "games",
        "3": "computer",
    }

    value := my_map["5"]
    if value == "" {
        fmt.Println("不存在")
    }
}

输出结果如下

不存在

由于map中的value有可能本身是存在的,但它的值为0,这时就会出现误判断。例如下面的"3",它已经存在,但它对应的值为0

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 22,
        "2": 11,
        "3": 0,
    }

    value := my_map["3"]
    if value == 0 {
        fmt.Println("不存在")
    }
}

输出结果如下

不存在

所以,应当使用第一种方式进行判断元素是否存在。

8. 迭代遍历 map

因为map是key/value类型的数据结构,key就是map的index,所以range关键字对map操作时,将返回key和value。

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 22,
        "2": 11,
        "3": 0,
        "4": 55,
        "5": 66,
    }

    for k, v := range my_map {
        fmt.Printf("key=%s, value=%d\n", k, v)
    }
}

输出结果如下

key=1, value=22
key=2, value=11
key=3, value=0
key=4, value=55
key=5, value=66

如果range迭代map时,只给一个返回值,则表示迭代map的key:

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 22,
        "2": 11,
        "3": 0,
        "4": 55,
        "5": 66,
    }

    for key := range my_map {
        fmt.Println("key=", key)
    }
}

输出结果

key= 1
key= 2
key= 3
key= 4
key= 5

9. 获取map中所有的key

Go中没有提供直接获取map所有key的函数。所以,只能自己写,方式很简单,range遍历map,将遍历到的key放进一个slice中保存起来。

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "Java":   11,
        "Perl":   8,
        "Python": 13,
        "Shell":  23,
    }

    // 保存map中key的slice
    // slice类型要和map的key类型一致
    keys := make([]string,0,len(my_map))

    // 将map中的key遍历到keys中
    for map_key,_ := range my_map {
        keys = append(keys,map_key)
    }

    fmt.Println(keys)
}

注意上面声明的slice中要限制长度为0,否则声明为长度4、容量4的slice,而这4个元素都是空值,而且后面append()会直接对slice进行一次扩容,导致append()后的slice长度为map长度的2倍,前一半为空,后一般才是map中的key。

10. 传递map给函数

map是一种指针,所以将map传递给函数,仅仅只是复制这个指针,所以函数内部对map的操作会直接修改外部的map。

例如,test()用于给map的key对应的值加1。

package main

import "fmt"

func main() {
    my_map := map[string]int{
        "1": 22,
        "2": 11,
        "3": 0,
        "4": 55,
        "5": 66,
    }
    fmt.Println("修改之前key=", my_map["3"])
    fmt.Println(my_map)

    fmt.Println("")

    test(my_map, "3")
    fmt.Println("修改之后key=", my_map["3"])
    fmt.Println(my_map)

}

func test(m map[string]int, key string) {
    m[key] += 1
}

输出结果如下

修改之前key= 0
map[1:22 2:11 3:0 4:55 5:66]
 
修改之后key= 1
map[1:22 2:11 3:1 4:55 5:66]

到此这篇关于Go语言学习之映射(map)的用法详解的文章就介绍到这了,更多相关Go语言映射内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • GO语言映射(Map)用法分析

    本文实例讲述了GO语言映射(Map)用法.分享给大家供大家参考.具体如下: 映射是一种内置的数据结构,用来保存键值对的无序集合. (1)映射的创建 make ( map [KeyType] ValueType, initialCapacity ) make ( map [KeyType] ValueType ) map [KeyType ] ValueType {} map [KeyType ] ValueType { key1 : value1, key2: value2, ... , key

  • Go语言映射内部实现及基础功能实战

    目录 写在前面 映射的内部实现和基础功能 内部实现 创建和初始化 使用映射 在函数间传递映射 写在前面 嗯,学习GO,所以有了这篇文章博文内容为<GO语言实战>读书笔记之一主要涉及映射相关知识 你要爱就要像一个痴情的恋人那样去爱,像一个忘死的梦者那样去爱,视他人之疑目如盏盏鬼火,大胆去走你的夜路.——史铁生<病隙碎笔> 映射的内部实现和基础功能 映射是一种数据结构,是用于存储一系列无序的键值对.类比Java里的Map,Python里的字典,可以理解为以哈希值做索引,期望索引可以在一

  • golang映射Map的方法步骤

    map是key-value数据结构,又称为字段或者关联数组.类似其他编程语言的集合 一.基本语法 var 变量名 map[keytype]valuetype // map 使用前要make // map 的key不能重复,重复了,以最后的key-value为准 // map 的key-value 是无序的 var a map[string]string a = make(map[string]string, 10) a["n1"] = "a" a["n2&

  • 浅析Go语言编程当中映射和方法的基本使用

    映射 Go编程提供的一个重要的数据类型就是映射,唯一映射一个键到一个值.一个键要使用在以后检索值的对象.给定的键和值,可以在一个Map对象存储的值.值存储后,您可以使用它的键检索. 定义映射 必须使用make函数来创建一个映射. 复制代码 代码如下: /* declare a variable, by default map will be nil*/ var map_variable map[key_data_type]value_data_type /* define the map as

  • Go语言学习之映射(map)的用法详解

    目录 1. 什么是 map 2. 创建 map 3. 访问 map 4. nil map和空map 5. map中元素的返回值 6. len()和delete() 7. 测试map中元素是否存在 8. 迭代遍历 map 9. 获取map中所有的key 10. 传递map给函数 1. 什么是 map Map 是一种无序的键值对的集合.Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值 Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash

  • Go语言学习之context包的用法详解

    目录 前言 需求一 需求二 Context 接口 emptyCtx valueCtx 类型定义 WithValue cancelCtx 类型定义 cancelCtx WithCancel timerCtx 类型定义 WithDeadline WithTimeout 总结 前言 日常 Go 开发中,Context 包是用的最多的一个了,几乎所有函数的第一个参数都是 ctx,那么我们为什么要传递 Context 呢,Context 又有哪些用法,底层实现是如何呢?相信你也一定会有探索的欲望,那么就跟

  • R语言学习ggplot2绘制统计图形包全面详解

    目录 一.序 二.ggplot2是什么? 三.ggplot2能画出什么样的图? 四.组装机器 五.设计图纸 六.机器的零件 1. 零件--散点图 1) 变换颜色 2) 拟合曲线 3) 变换大小 4) 修改透明度 5) 分层 6) 改中文 2. 零件--直方图与条形图 1) 直方图 2) 润色 3) 条形图 3. 零件--饼图 4. 零件--箱线图 5. 零件--小提琴图 6. 零件打磨 7. 超级变变变 8. 其他常用零件 七.实践出真知 八.学习资源 九.参考资料 一.序 作为一枚统计专业的学

  • Java Map集合用法详解

    目录 Map集合的概述 常用方法: 遍历方式: Map的实现类: HashMap TreeMap 集合嵌套(补充知识): 高频面试题 1.Map 2.HashMap的底层实现 Map集合的概述 概述:interface Map<K,V> 其中K是键的类型,键是唯一的,不重复.V是值的类型,是可以重复.且每个键可以映射最多一个值.注意的是如果存在两个相同的键时,则会将现在的值替换之前的值. 创建方式:以多态的形式创建对象. 特点: 键值对映射关系 一个键对应一个值 键不能重复,值可以重复 元素存

  • C#学习笔记- 随机函数Random()的用法详解

    Random.Next() 返回非负随机数: Random.Next(Int) 返回一个小于所指定最大值的非负随机数 Random.Next(Int,Int) 返回一个指定范围内的随机数,例如(-100,0)返回负数 1.random(number)函数介绍 见帮助文档,简单再提一下,random(number)返回一个0~number-1之间的随机整数.参数number代表一个整数. 示例: trace(random(5)); 2.Math.random() 见帮助文档.返回一个有14位精度的

  • Linux Shell Map的用法详解

    Map定义: 在使用map时,需要先声明,否则结果可能与预期不同,array可以不声明 方式1: declare -A myMap myMap["my03"]="03" 方式2: declare -A myMap=(["my01"]="01" ["my02"]="02") myMap["my03"]="03" myMap["my04&qu

  • R语言学习之线图的绘制详解

    目录 线图 单线图 多线图 横轴文本线图 线图 线图是反映趋势变化的一种方式,其输入数据一般也是一个矩阵. 单线图 假设有这么一个矩阵,第一列为转录起始位点及其上下游5 kb的区域,第二列为H3K27ac修饰在这些区域的丰度,想绘制一张线图展示. profile="Pos;H3K27ac -5000;8.7 -4000;8.4 -3000;8.3 -2000;7.2 -1000;3.6 0;3.6 1000;7.1 2000;8.2 3000;8.4 4000;8.5 5000;8.5"

  • Go语言学习笔记之文件读写操作详解

    目录 文件写 文件读 小结 文件操作比较多,分为几篇来写吧.首先是文件的读写,在平时的工程化操作中使用最多. 文件写 样例代码如下 package main import ( "bufio" "fmt" "io" "os" ) //写文件 func DoWriteFile() error { _filePath := "./test.txt" _file, _err := os.OpenFile(_file

  • Golang学习之反射机制的用法详解

    目录 介绍 TypeOf() ValueOf() 获取接口变量信息 事先知道原有类型的时候 事先不知道原有类型的时候 介绍 反射的本质就是在程序运行的时候,获取对象的类型信息和内存结构,反射是把双刃剑,功能强大但可读性差,反射代码无法在编译阶段静态发现错误,反射的代码常常比正常代码效率低1~2个数量级,如果在关键位置使用反射会直接导致代码效率问题,所以,如非必要,不建议使用. 静态类型是指在编译的时候就能确定的类型(常见的变量声明类型都是静态类型):动态类型是指在运行的时候才能确定的类型(比如接

  • Java常用集合之Set和Map的用法详解

    目录 常用Set集合 Set集合的特点 HashSet 创建对象 常用方法 遍历 常用Map集合 Map集合的概述 HashMap 创建对象 常用方法 遍历 HashMap的key去重原理 常用Set集合 Set集合的特点 ​ Set接口下的集合都会有以下特点 不能存储重复元素 没有索引 HashSet HashSet集合的特点 底层数据结构是哈希表 存储元素的顺序和遍历获取出来的顺序可能不一致 没有索引 集合中不能存储重复元素 创建对象 HashSet<元素数据类型> set = new H

随机推荐