Golang语言之映射(map)快速入门篇

简介: 这篇文章是关于Go语言中映射(map)的快速入门教程,涵盖了map的定义、创建方式、基本操作如增删改查、遍历、嵌套map的使用以及相关练习题。

                                              作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.映射(map)定义

1.映射(map)概述

映射(map)是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。

Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现。

映射(map)是Go语言中内置的一种类型,它将键值相关联,我们可以通过key来获取对应的value,有点类似于其他语言的集合。

映射(map)的特点:
    - 1.map结合在使用前一定要make;
    - 2.map的key-value是无序的;
    - 3.key是不可以重复的,如果遇到重复,后一个value会替换前一个value;
    - 4.不同的key,其value是可以重复的;

2.map的语法格式

Go语言中map的定义语法如下:
    map[KeyType]ValueType

map类型的变量默认初始值为nil,需要使用make()函数来分配内存。语法为:
    make(map[KeyType]ValueType, [cap])

    相关字段说明:
    KeyType:
      表示键的类型。
    ValueType:
      表示键对应的值的类型。
    cap
      map的容量,该参数可选,但建议在初始化map的时候就为其指定一个合适的容量。

温馨提示:
    - 1.key,value的类型包括但不限于bool,数值型,string,指针,chan,还可以只包含前面几个类型的接口,结构体,数组等;
    - 2.key部分通常为int,string类型,value通常为数字(整数,浮点数),string,map,结构体;
    - 3.key部分不可以是slice,map,function等类型;

3.map的三种创建方式

3.1 先声明在make

package main

import "fmt"

func main() {

    // 1.声明map变量,但并没有分配堆内存空间
    var dongMan map[int]string

    // 2.必须通过make函数进行初始化,才会在堆内存中分配空间
    dongMan = make(map[int]string, 5) // map可以存放5个键值对,但实际存储超过5个依旧是可以的

    // 3.将键值对存储map中
    dongMan[20230925] = "《仙逆》"
    dongMan[20200725] = "《凡人修仙传》"
    dongMan[20201129] = "《吞噬星空》"
    dongMan[20220129] = "《永生》"
    dongMan[20140731] = "《画江湖之不良人》"
    dongMan[20131214] = "《师兄啊师兄》"
    dongMan[20021003] = "《火影忍者》"
    dongMan[20080517] = "《葫芦兄弟》"
    dongMan[19990723] = "《西游记》"

    // 4.输出集合
    fmt.Printf("dongman = %v\n", dongMan)
}

3.2 直接使用make初始化map

package main

import "fmt"

func main() {

    // 1.初始化map类型
    language := make(map[string]uint16)

    // 2.赋值
    language["C"] = 1972
    language["C++"] = 1983
    language["Python"] = 1989
    language["JAVA"] = 1995
    language["Golang"] = 2007
    language["Scala"] = 2003
    language["Ruby"] = 1993
    language["Php"] = 2004
    language["HTML"] = 1989
    language["CSS"] = 1994
    language["JavaScript"] = 1995

    // 3.查看map数据
    fmt.Printf("language = [%v]\n", language)
}

3.3 直接赋值初始化map

package main

import "fmt"

func main() {

    dbInfo := map[string]string{
        "Username": "jasonyin2020",
        "Password": "yinzhengjie",
        "DbHost":   "www.yinzhengjie.com",
        "DbPort":   "3306",
        "DbName":   "wordpress",
    }

    fmt.Printf("userInfo = %v\n", dbInfo)
}

二.map基本使用

1.map的增删改查

package main

import "fmt"

func main() {
    // 1.定义map
    constellation := make(map[string]string)

    // 2.增加
    constellation["金牛座"] = "土象星座: 0420-0520"
    constellation["处女座"] = "土象星座: 0823-0922"
    constellation["摩羯座"] = "土象星座: 1222-0119"

    // 3.修改
    constellation["狮子座"] = "火象星座: 0723-0822"

    fmt.Printf("删除前: len(constellation) = %d\n", len(constellation))

    // 4.删除指定map的key,若key不存在,并不会报错
    delete(constellation, "摩羯座")
    fmt.Printf("删除后: len(constellation) = %d\n", len(constellation))

    // 5.查找,判断某个键是否存在
    value, ok := constellation["狮子座"]
    if ok {
        fmt.Printf("狮子座的出生日期: %v\n", value)
    } else {
        fmt.Println("查无此人")
    }

    fmt.Printf("星座: %v\n", constellation)

}

2.map的遍历

package main

import "fmt"

func main() {
    constellation := make(map[string]string)

    constellation["金牛座"] = "土象星座: 0420-0520"
    constellation["处女座"] = "土象星座: 0823-0922"
    constellation["摩羯座"] = "土象星座: 1222-0119"
    constellation["狮子座"] = "火象星座: 0723-0822"

    // Go语言中使用for range遍历map,遍历map时的元素顺序与添加键值对的顺序无关。
    for key, value := range constellation {
        fmt.Printf("key = %v, value = %v\n", key, value)
    }

    fmt.Println("----- 我是分割线 -----")

    // 但我们只想遍历key的时候,仅需使用一个参数来接收哟~
    for k := range constellation {
        fmt.Printf("key = %v\n", k)
    }

}

3.嵌套map遍历

package main

import "fmt"

func main() {

    dongMan := make(map[string]map[int]string)

    // 由于map的值为map类型,因此我们需要对值先进行make再使用,否则会抛出异常
    dongMan["腾讯视频"] = make(map[int]string, 3)
    dongMan["腾讯视频"][20230925] = "《仙逆》"
    dongMan["腾讯视频"][20201129] = "《吞噬星空》"
    dongMan["腾讯视频"][20140731] = "《画江湖之不良人》"

    // 由于map的值为map类型,因此我们需要对值先进行make再使用,否则会抛出异常
    dongMan["B站"] = make(map[int]string, 2)
    dongMan["B站"][20200725] = "《凡人修仙传》"
    dongMan["B站"][20220129] = "《永生》"

    // 由于map的值为map类型,因此我们需要对值先进行make再使用,否则会抛出异常
    dongMan["优酷"] = make(map[int]string, 2)
    dongMan["优酷"][20131214] = "《师兄啊师兄》"
    dongMan["优酷"][20021003] = "《火影忍者》"

    for k1, v1 := range dongMan {
        fmt.Printf("k1 = %v\n", k1)

        for k2, v2 := range v1 {
            fmt.Printf("[%v]动漫的发行时间是: [%d]\n", v2, k2)
        }
    }
}

4.元素为map类型的切片

package main

import (
    "fmt"
)

func main() {
    // 定义一个长度为3的切片
    var mapSlice = make([]map[string]string, 3)

    // 对切片的各个元素进行遍历
    for index, value := range mapSlice {
        fmt.Printf("index: %d value: %v\n", index, value)
    }

    fmt.Println("----- 分割线 -----")

    // 对切片中的第一个(索引下标为0)map元素进行初始化
    mapSlice[0] = make(map[string]string, 10)
    mapSlice[0]["name"] = "Jason Yin"
    mapSlice[0]["password"] = "123456"
    mapSlice[0]["address"] = "北京市昌平区沙河镇"

    for index, value := range mapSlice {
        fmt.Printf("index: %d value: %v\n", index, value)
    }
}

5.值为切片类型的map

package main

import (
    "fmt"
)

func main() {
    // 定义一个map类型
    var sliceMap = make(map[string][]string, 3)

    key := "中国"
    value, ok := sliceMap[key]
    if !ok {
        // 如果key="中国"不存在,则对其值进行初始化为一个容量为2的字符串切片。
        value = make([]string, 0, 2)
    }

    // 紧接着,由于切片是引用类型,我们往该切片中添加2个字符串类型元素
    value = append(value, "北京", "上海")

    fmt.Printf("地址: %p, 数据: %v, 长度: %d, 容量: %d\n", value, value, len(value), cap(value))

    // 往切片追加元素,原有的切片底层数组将存不下,于是会产生新的底层数组哟~
    value = append(value, "深圳", "石家庄", "西安")
    fmt.Printf("地址: %p, 数据: %v, 长度: %d, 容量: %d\n", value, value, len(value), cap(value))

    // 注意,此处我们切片进行赋值给map的key。
    sliceMap[key] = value
    fmt.Println(sliceMap)
}

三.练习题

1.写一个程序,统计一个字符串中每个单词出现的次数

package main

import (
    "fmt"
    "strings"
)

func main() {

    // 统计一个字符串中每个单词出现的次数
    s1 := "I love you , and you ?"

    // 将字符串按照空格子串进行切割
    res := strings.Split(s1, " ")

    // 初始化用于单词统计的map
    var wordCount = make(map[string]int, 10)

    // 如果单词不存在,则将其值设置为1,若存在,则将其值进行加一操作。
    for _, value := range res {
        _, ok := wordCount[value]
        if !ok {
            wordCount[value] = 1
        } else {
            wordCount[value]++
        }
    }

    // 遍历字典
    for k, v := range wordCount {
        fmt.Printf("%s: %d\n", k, v)
    }

}

2.看代码手写结果

package main

import (
    "fmt"
)

func main() {
    // 自定义一个Map类型,底层对应的是一个map类型哟~
    type Map map[string][]int

    // 初始化咱们的自定义类型
    m := make(Map)
    s1 := []int{100, 200}
    s1 = append(s1, 300)
    fmt.Printf("s1 = %+v\n", s1)

    m["JasonYin"] = s1
    s1 = append(s1[:1], s1[2:]...)
    fmt.Printf("s1 = %+v\n", s1)
    fmt.Printf("m['JasonYn'] = %+v\n", m["JasonYin"])
}
目录
相关文章
|
12天前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
43 4
Golang语言之管道channel快速入门篇
|
12天前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
36 4
Golang语言文件操作快速入门篇
|
12天前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
40 3
Golang语言之gRPC程序设计示例
|
12天前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
36 4
|
12天前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
23 4
Golang语言goroutine协程篇
|
12天前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
20 3
Golang语言之Prometheus的日志模块使用案例
|
12天前
|
Go
Golang语言错误处理机制
这篇文章是关于Golang语言错误处理机制的教程,介绍了使用defer结合recover捕获错误、基于errors.New自定义错误以及使用panic抛出自定义错误的方法。
35 3
|
12天前
|
Go
Golang语言之函数(func)进阶篇
这篇文章是关于Golang语言中函数高级用法的教程,涵盖了初始化函数、匿名函数、闭包函数、高阶函数、defer关键字以及系统函数的使用和案例。
16 3
Golang语言之函数(func)进阶篇
|
12天前
|
Go
Golang语言之函数(func)基础篇
这篇文章深入讲解了Golang语言中函数的定义和使用,包括函数的引入原因、使用细节、定义语法,并通过多个案例展示了如何定义不返回任何参数、返回一个或多个参数、返回值命名、可变参数的函数,同时探讨了函数默认值传递、指针传递、函数作为变量和参数、自定义数据类型以及返回值为切片类型的函数。
17 2
Golang语言之函数(func)基础篇
|
12天前
|
Go
Golang语言之切片(slice)快速入门篇
这篇文章是关于Go语言中切片(slice)的快速入门教程,详细介绍了切片的概念、定义方式、遍历、扩容机制、使用注意事项以及相关练习题。
21 5